Use JDK , I can compile a .java file into a .class file, then I can run the .class file, does this mean that the .class file is the final executable file running on JVM ?
Moreover, what's a jar file ? and the difference between jar file and .class file ?
1. A class file is a byte code files, which is executed by the JVM, it has no meaning outside the JVM. Making it meaningful only on JVM but not outside, is what makes every java program run in its own sandbox .
2. Jar file is a collection of all the class file, libraries necessary to run the program, consider its an easy way to pack all the files and depending library and providing a single file. We also have Runnable Jars which can be known as Executable Jar
////////// EDITED PART//////////////////
Now this byte-code is converted to machine level executable during Run-time by the JIT (Just In Time Compiler). JIT will look for the runtime intensive part of the program during Runtime, and then it will convert it into machine level executable, this part of the program is known as Hot-spot, and the JIT is known as Hot-Spot-Compiler.
A jar (java archive) as its name says is an archive or collection of java classes that are ready to be executed.
A java decompiler is a tool that makes a reverse engineering from .class extension to .java extension.
To make a jar use following link
http://docs.oracle.com/javase/tutorial/deployment/jar/build.html
Or using windows command promt
jar cf JAR_FILE_NAME FILE_NAMES_OR_DIRECTORY_NAME
e.g.
jar cf MyApp1.jar C:\JavaProject\MyApp
Related
This is very close to what I'm trying to accomplish. How to compile and run kotlin program in command line with external java library
I really want to learn how to compile and run simple code that includes libraries but am getting a bit lost when it comes to including classpaths.
I’m currently trying to compile and run
import kotlinx.serialization.*
import kotlinx.serialization.json.*
#Serializable
data class Project(val name: String, val language: String)
fun main() {
// Serializing objects
val data = Project("kotlinx.serialization", "Kotlin")
val string = Json.encodeToString(data)
println(string) // {"name":"kotlinx.serialization","language":"Kotlin"}
// Deserializing back into objects
val obj = Json.decodeFromString<Project>(string)
println(obj) // Project(name=kotlinx.serialization, language=Kotlin)
}
using
kotlinc -cp "C:\PROGRA~1\Kotlin\lib\kotlinx-serialization-runtime-1.0-M1-1.4.0-rc.jar" main.kt
to compile with this compiler
https://blog.jetbrains.com/kotlin/2020/07/kotlin-1-4-rc-released/
allowed lib at bottom of the article
that's where kotlinx-serialization-runtime-1.0-M1-1.4.0-rc.jar is coming from. I chose this runtime jar because when I use the new kotlin 4.0.21 compiler it requires the kotlin-serialization-runtime-1.0.1.jar which you need to build yourself but when I download the source and run gradle build it doesn't seem to get generated (separate problem but would love to know how to build the runtime jar myself)
when I try and run I get
Exception in thread "main" java.lang.NoClassDefFoundError: kotlinx/serialization/json/Json
at MainKt.main(main.kt:12)
at MainKt.main(main.kt)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.jetbrains.kotlin.runner.AbstractRunner.run(runners.kt:64)
at org.jetbrains.kotlin.runner.Main.run(Main.kt:149)
at org.jetbrains.kotlin.runner.Main.main(Main.kt:159)
Caused by: java.lang.ClassNotFoundException: kotlinx.serialization.json.Json
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:435)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 9 more
I know I need to include a classpath when I run
kotlin MainKt
but have tried everything with no success
I've tried many different combinations of things including
compiling with and without
-Xplugin="C:\PROGRA~1\Kotlin\lib\kotlinx-serialization-compiler-plugin.jar doesn't seem to make a difference so I left it off.
I have tried compiling to both a java .jar as well as a kotlin .class file both seem to need classpath information at runtime. I would rather compile to a kotlin .class and keep java out of this until I really need it. This way I can learn what java is really doing in my application.
I guess what I really want to know is how one can determine what is required at runtime for an executable to run. I found this site which helps show dependencies but is for older versions of kotlin https://kotlin.binarydoc.org/org.jetbrains.kotlin/kotlin-compiler-dist/1.3.71/package?package=kotlinx.serialization
I’ve also been peaking into the .class files using https://github.com/google/android-classyshark
and
https://github.com/borisf/classyshark-bytecode-viewer
but still when people tell others, on StackOverflow, what classpath they need to use to solve their problem it seems like magic. Can someone out there teach me how to fish without gradle?
p.s. If anyone has any good resources on learning the internals of how gradle is building the project. I've looked here a bit https://docs.gradle.org/current/userguide/userguide.pdf but didn’t seem to help. maybe I missed something. Also, this page https://kotlinlang.org/docs/reference/serialization.html#example-json-serialization seems to have what I need but can't seem to transfer that to what the command line needs.
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1")
}
what does this mean? I think this is referring to this https://github.com/Kotlin/kotlinx.serialization
but then how can I build what I need from this repo and use it to allow my application to know where its runtime dependencies are? ugh. I really wanted to figure all this out myself, but I must kneel to the internet gods for this one. Sorry, my post is a mess. I love to learn.
It took some time but I was able to build and run the serialization sample found at https://github.com/Kotlin/kotlinx.serialization on the command line using the current kotlinc compiler and the kotlinx.serializtion.1.0.1 library.
Here are the direct links to the compilers and libs
kotlinc and kotlinc-native v1.4.20
https://github.com/JetBrains/kotlin/releases/tag/v1.4.20
Kotlinx.serialization v1.0.1
https://github.com/Kotlin/kotlinx.serialization/releases/tag/v1.0.1
These both can also be found in the 1.4.20 releases blog post under the section titled How To Update:
https://blog.jetbrains.com/kotlin/2020/11/kotlin-1-4-20-released/
Setting Up Katlin’s .jar Libraries
After updating my path to point to the new compilers I still needed to build the serialization libs. This was as simple as running gradle build in the root directory of the unzipped kotlinx-serialization-1.0.1 folder. Make sure to set your JAVA-HOME system variable before you do this or it won’t work.
Once it's built you need to grab both the kotlinx-serialization-json-jvm-SNAPSHOT-1.0.1.jar and the kotlinx-serialization-core-jvm-SNAPSHOT-1.0.1.jar files and move them into the project directory. This definitely confused me because I had found a runtime lib for kotlinx serialization on the MVN repository site that was one jar file, but I wasn't seeing it after building the 1.0.1 libraries. Once I extracted the 1.0.1 runtime jar I found online, by renaming the .jar to .zip, it became apparent that it consisted of both the contents of the core and json jars. Don’t use the kotlinx-serialization-1.0.1-SNAPSHOT.jar. This jar only contains a blank MANIFEST.ms file. You can find the kotlinx-serialization-core-jvm-1.0.1-SNAPSHOT.jar in the kotlinx.serialization-1.0.1\core\build\libs folder and the kotlinx-serialization-json-jvm-1.0.1-SNAPSHOT.jar in the kotlinx.serialization-1.0.1\formats\json\build\libs folder. anyways.
Compiling Your .jar Library
once you have the jars in your project folder you can build your project
I included my cleanbuildandrun.sh shell script down below for easy reference.
My first attempt 1) was to try and build the project without compiling it to a .jar library file. This was a complete failure. I got it to compile but running the project proved much harder. I was unable to tell kotlin where the libraries were at runtime. I tried so many different things Including trying to point it to a manifest file I created but nothing seemed to work. It seems you need to build an executable jar in order to make this work. which brings me to my second try 2). This is where I found more success.
Attempt 2)
First you need to include the kotlinx-serialization-compiler-plugin.jar using the "-Xplugin" compiler flag. My understanding is that plugins are used to define annotations to the compiler like #Serializable. You can find this jar file in the lib folder inside the compiler you just downloaded. I copied this into my projects /lib folder next to the other jar files to make things self-contained and portable.
Next you need to tell the compiler where to find the library classes you want to access using the "-classpath" or "-cp" compiler flag.
Make sure to include kotlin runtime libraries using the "-include-runtime" compiler flag. This will bundle the kotlin standard class libraries within your jar so you don’t need to point at them during runtime.
Last direct the compiler to build a jar file by providing the -d compiler flag with the name and extension of your soon to be .jar file. That’s it, your off compiling.
Example Shell Script:
#!/bin/bash
sh clean.sh
case $1 in
1) # Comming Soon
kotlinc -verbose -Xplugin="lib\kotlinx-serialization-compiler-plugin.jar" \
-cp "lib\kotlinx-serialization-json-jvm-1.0.1.jar;lib\kotlinx-serialization-core-jvm-1.0.1.jar" \
main.kt
;;
2) # Working
kotlinc main.kt -Xplugin="lib\kotlinx-serialization-compiler-plugin.jar" \
-cp "lib\kotlinx-serialization-json-jvm-1.0.1.jar;lib\kotlinx-serialization-core-jvm-1.0.1.jar" \
-include-runtime -d main.jar
jar ufm Main.jar ManifestAdditions.txt lib
kotlin main.jar
;;
3) # Comming Soon
kotlinc-native main.kt -verbose -Xplugin="lib\kotlinx-serialization-compiler-plugin.jar" \
-cp "lib\kotlinx-serialization-json-jvm-1.0.1.jar;lib\kotlinx-serialization-core-jvm-1.0.1.jar" \
-manifest ManifestAddition.txt -o main
;;
esac
Running your .jar Library
By default, when you compiled the jar it created a MANIFEST.ms file that it uses to tell your jar library where the entry point is. which would be enough if we weren’t using additional libraries in our application. So next we need to add those libraries to the jar file we compiled while at the same time updating its MANIFEST.ms file to tell it where those libraries are within that jar file. We can use the cli tool jar to accomplish this. With the command:
jar ufm Main.jar ManifestAdditions.txt lib
we are able to update the current jar file.
u - tells jar we want to update an existing jar file
f - indicates that we are providing the jar file we want to update on the cmd line
m - indicates that we will be providing the manifest file
The Manifest .txt file should look like this:
Main-Class: MainKt
Class-Path: lib\kotlinx-serialization-core-jvm-1.0.1.jar lib\kotlinx-serialization-json-jvm-1.0.1.jar
Make sure to add a new line at the end of the file or it won’t parse the Class-Path.
That’s it. Now we have an executable jar file that we can use to run our serialization code on the command line:
kotlin main.jar
should output:
{"name":"kotlinx.serialization","language":"Kotlin"}
Project(name=kotlinx.serialization, language=Kotlin)
Post Mark
I would really like to turn this answer into a blog post that explains how to use the kotlin compiler, with libraries, on the command line. The information is out there but it seems to be scattered. I would like to include how to compile and run without using jar files, if that’s even possible, as well as how to compile and run using the native compiler. If anyone can help fill in these gaps it would be much appreciated. I think this information could help others learn how to set up simple test environments so they can better understand the functionality of these libs without having to set up a build script. This will be my first attempt at creating a tutorial type blog post so any information would really help.
I've tried to convert a tcl file to a exe file by using FREEWRAP.EXE .
It works on most of the files, but there is one file which includes a line of code "load TLTcl.dll " which will always fail.
When I run the tcl file with activetcl, it was fine.
Since I convert the tcl file to a exe file and put TLTcl.dll on the same folder with it, the exe always crash while executing.
I wonder how to load a dll file in the tcl file when I turn a tcl to a exe.
Thanks a lot !
puts "Starting FLASH script"
puts "FLASH write will be performed now, make sure you have an extra flash... "
#load 10 lira tcl DLL
load TLTcl.dll
It sounds like TLTcl.dll was not built with stubs support, which means that it links against a real tcl.dll (possibly with a version number in the name) and freewrap doesn't use that; it uses a statically-linked build so that the whole system can be a simply-redistributable file.
You'll need to rebuild TLTcl.dll with stubs support enabled (assuming it is a DLL that implements a Tcl extension). That's not usually too difficult, as it is a matter of defining the USE_TCL_STUBS preprocessor symbol when compiling all the files, and linking against the tclstub static library; it probably has the version number embedded in the filename (and the version of the Tcl headers you compile with and the stub library you link with must match). Note that it is a property of Tcl's API that if you build against the Tcl 8.5 stubbed API, you can be loaded into a Tcl 8.6 interpreter. (Indeed, that level of forward compatibility is there from about 8.0.6† through to 8.7, which is still in active development so you won't be using it yet.)
†This was a version that was only released to a few commercial partners. Everyone else used newer supported versions.
It is my understanding that the jython compiler compiles the jython code into java source, and then compiles the java code into bytecode in either a $py.class file or a .class file (or I'm totally wrong and this is not how it works, but that doesn't really change the question.)
Is there a way for me to end up with a .java file with the resulting java source after I compile my program instead of ending up with a $py.class file or a .class file? If so, where would I then be able to find said file?
Aftern reading Jython and Java Integration it appears that this is no longer the case.
Prior to Jython 2.5, the standard distribution of Jython included a utility known as jythonc. Its main purpose was to provide the ability to convert Python modules into Java classes so that Java applications could seamlessly make use of Python code, albeit in a roundabout fashion. jythonc actually compiles the Jython code down into Java .class files and then the classes are utilized within the Java application.
[...]jythonc is no longer packaged with the Jython distribution beginning with the 2.5 release.
I am trying to package a jython program into an executable jar which the user can simply double-click to run without installing jython ahead of time. Ultimately, I would like to include an additional library which I wrote with the jar, but at the moment I am just trying to package a simple program and have it run from the jar.
I have tried following the jar instructions in the "Using the Jar Method" section here: Jython FAQ: Using the Jar Method
I have also looked at slides 25-28 here: Jython Update 2012 slides
And finally here:
stackoverflow Question: Distributing My Python Scripts as Jars with Jython
I have installed jython 2.5.3, jvm 1.6, and python 2.7.3 on my mac which is running OS X 10.8.3.
These are the steps I go through to create the jar and run it:
Create a copy of jython.jar from my jython installation directory.
zip -r jython_copy.jar Lib (where Lib is the folder in the jython installation directory)
cp myJythonProgram.py __run__.py (myJythonProgram.py does not include an 'if name == main' line)
zip jython_copy.jar __run__.py
export CLASSPATH=/path/to/my/app/jython_copy.jar:$CLASSPATH
I have tried running the jar using all three of these methods:
java org.python.util.jython -jar myapp.jar
java -cp myapp.jar org.python.util.jython -jar myapp.jar
java -jar myapp.jar -jar myapp.jar
This works if my program doesn't use any import statements.
However I am running into an issue where some python packages are not able to be found when I run the jar. For instance, I get the error "ImportError: No module named random" when I include the line from random import random in my program. No errors occur on lines in the program when I import from javax.swing, java.awt, time, or math.
Additionally, I tried to package a jar with my library and a jython program which imports my library using the previous steps as well as the following additional steps:
zip jython_copy.jar myLibrary.jar
jar ufm jython_copy.jar othermanifest.mf
othermanifest.mf only contains the line Class-Path: ./myLibrary.jar.
This too gives the error "ImportError: No module named myLibrary"
I would appreciate any insight into what I am doing incorrectly or other steps I should take.
Thanks!
I realized what the problem was and I wanted to document it in case anyone else has the same problems.
I was using the jython.jar file that came in the standard installation of Jython, and NOT the standalone jython.jar (the instructions at Using the Jar Method mentions this, but the instructions at Building Jars do not). I am still unsure why copying the Lib/ folder of the standard installation into the jython.jar that came with that installation didn't work on my system. However, once I used the standalone jar, things started to work more smoothly.
Additionally, I was able to get my library to work with the packaged file by doing three things in addition to the steps I laid out in my question:
Exploding the standalone jython.jar and copying the folder with all of my library files into Lib, then create a new jar. This seemed to be the easiest way to include my library and allows me to package everything into a single jar.
I discovered after reading Frank Wierzbicki's answer in Why does Jython refuse to find my Java package? that because I am now using the standalone jar, I could no longer use imports of the style from java.awt import *, instead I needed to fully specify each thing I was importing, for example from java.awt.Font import PLAIN, BOLD, ITALIC. So I went through the library's imports and fixed the few that were of the wrong style.
Now that I am adding my Library directly to the Jar's Lib folder, instead of writing Class-Path: ./myLibrary.jar in othermanifest.mf, I put Main-Class: org.python.util.JarRunner as per Frank Wierzbicki's answer in the post I mentioned in my question: Distributing my Python scripts as JAR files with Jython?
This allowed me to create a double-clickable executable jar containing my library and jython file that I wanted to run.
There are two solutions. They both work, but one better than the other.
I believe you can rename your python script as __run__.py, place that file inside the .jar file, and pass the .jar file through a python interpreter. See https://wiki.python.org/jython/UserGuide#invoking-the-jython-interpreter for more.
Multiple methods to run Jython from the java code while running through JVM are described here, at the Jython documentation.
EDIT:
You can execute a command line code that runs the python file you want.
Link to an example of running command line code from java here.
How do I make the manifest available during a Maven/Surefire unittest run "mvn test" ?
I have an open-source project that I am converting from Ant to Maven, including its unit tests. Here's the project source repository with the Maven project:
http://github.com/znerd/logdoc
My question pertains to the primary module, called "base". This module has a unit test that tests the behaviour of the static method getVersion() in the class org.znerd.logdoc.Library. This method returns:
Library.class.getPackage().getImplementationVersion()
The getImplementationVersion() method returns a value of a setting in the manifest file. So far, so good. I have tested this in the past and it works well, as long as the manifest is indeed available on the classpath at the path META-INF/MANIFEST.MF (either on the file system or inside a JAR file).
Now my challenge is that the manifest file is not available when I run the unit tests:
mvn test
Surefire runs the unit tests, but my unit test fails with a mesage indicating that Library.getVersion() returned null.
When I want to check the JAR, I find that it has not even been generated. Maven/Surefire runs the unit tests against the classes, before the resources are added to the classpath.
Further investigation shows Surefire generates its own JAR file in a temporary directory, e.g.
/private/var/folders/TR/TREvj1wIHYyAcUy-xmc3UU+++TI/-Tmp-/surefirebooter7448562488934426857.jar
And then uses this JAR to load the Library class. This JAR does not contain the resources I stuck under src/main/resources. So putting a META-INF/MANIFEST.MF file also does not work.
So how do I tell Surefire to have my META-INF/MANIFEST.MF file available from the same class loader as the Library class.
Note that I use Maven 2.2.0, Java 1.6.0_17 on Mac OS X 10.6.2, with JUnit 4.8.1.
Well, as you pointed you, the problem is that the MANIFEST.MF is generated during package and directly included in the final jar and all this occurs after test. So I guess you'll have to either:
provide your own MANIFEST.MF (that would be available in target/classes before being merged during package). I don't know if this is an option (and if it will work).
put and run your test from another module depending on the JAR.