How does an executable jar file work with another program - java

I want to know how does an executable jar file (which is added as a library) work with the main program.
For example when an executable jar file is added, and if it was not called within the source code of the main program, does it have any effect?
Is an executable jar file the same as a run time library?

An "executable jar file" is simply one that has a class that defines a main method and where the jar file maintains metadata about where to find this main method.
If this jar is not the jar used to launch the JVM, then this metadata is ignored and the jar is treated just like any other jar file (no effect unless explicitly used by something else).

Answer is No, It is just standard JAR file which contains a class with Main method init. This main method's location information gets stored in metadata.
If you run this jar file then this class & thus main method gets called.
Otherwise it is just normal JAR file. You can add it to any application's classpath & it has same effects as other normal JAR files. Main method still exist but won't get executed.

Related

Call methods on class in exectuable jar file?

I've created a method in a Java class that does some encryption. This class utilizes methods from some external jar files. The requestor of this method has asked that I include my class and the external jar files in one jar file. I am using Eclipse for my IDE. As I understand it, I need to create an executable jar file in Eclipse, in order to package the external jar files in my own jar file. In my project, I also created a basic class with a main method in my project that simply calls my method mentioned above (to provide a "main class" for the run configuration for the executable jar). I exported my project to an executable jar file, and verified that it runs (java -jar jar-file-name) in a command prompt window. I created a second test project in Eclipse, and added my executable jar file to the build path. I created a simple class in this test project with a main method that calls the method mentioned above (on the class in my executable jar file). This compiled, so I exported this project to a normal jar file, and tried to run it (with java -classpath executable-jar-file-mentioned-above;test-project-jar-file class-name. This fails with a NoClassDefFoundError, referencing a class found in one of the external jar files.
What am I missing here? This is my first experience with an executable jar file. Is there anything special that needs to be done when calling methods on a class in an executable jar file?
There is nothing special about executable jar files. The only difference is that an executable jar file defines a main class (with a main() method) that will be started when you run java -jar ....
A jar file is in fact a plain zip file containing classes, resources and some additional meta-information.
When you run your jar file and get a ClassNotFoundException, this is an issue with you class path. So you are somehow missing classes, you depend on, located in your external lib.
There are two ways to fix your issue:
Add the library jar to the class path when you run your runnable jar
Repackage your executable jar to contain all the classes from the external library
I don't know what the Eclipse export functions do. But I would recommend taking a look at the exported jar file first using your favorite zip utility.
I would also recommend using a build tool like maven to create your jar. Here is an example how this can be done using the maven assembly plugin: https://www.mkyong.com/maven/create-a-fat-jar-file-maven-assembly-plugin/

How does a jar file get executed? Do the classes get extracted somewhere?

We know that jar is a compressed archive file format which acts as a container for compiled java classes and conf files. As far as I know, for reading any contents from a compressed container file, first they need to be extracted somewhere.
So how does the JVM execute classes inside the jar? Does it extract the contents of the jar to a temp location and then executes the classes?
The JVM is capable of loading classes or files from a jar file without extracting the jar to temp files.
This functionality is also available to you in the standard library, see the JarFile for more information.
So no, the JVM does not extract a jar to temp files, classes (and resources) are simply loaded on demand.
A jar file is basically a zip file with a predefined entry "META-INF/MANIFEST.MF" (this is only mandatory in case of an executable jar). This MANIFEST.MF entry (file) contains some information read by the JVM. More on the Manifest files:
Working with Manifest Files: The Basics
In case of an executable jar the Manifest file also contains the main class that should be loaded and whose public static void main(String[]) method to be called in order to start the application. The Main-Class manifest entry specifies the main class:
Main-Class: classname
No The jvm extracts the jar file to the memory and not to the file. It reads the MANIFEST.MF inside META-INF which has an entry for the main class. Jvm looks for the public static void main class inside this main class. This is how jvm finds the main class and executes the executable jar files

Java classpath (-cp) and passing execution to that class

I am relatively new to Java but have a fair understanding about how the class path works with respect to providing a list of folder and jars that make classes available to other classes.
I have compiled a JAR (lets say example.jar) that has a main function where execution normally begins. Sometimes I want execution to begin in a different class (lets say myAlternateClass.java), with its own main. I can achieve this by doing using the -cp argument when executing the jar, for example;
java -cp example.jar myAlternateClass
This works as I require but I am unsure of what exactly is happening here.
I'm not 100% sure on exactly what you're looking for, but I'll give it a shot.
There are two ways to use a jar file. If the jar file has a Main-Class specified in its META-INF/MANIFEST.MF file, then you can load java with the jar file and execution will start in the main method of that class.
java -jar example.jar
On the other hand, a jar file can simply be loaded onto the classpath, which makes all of the classes within it available for use. This is the example you are giving:
java -cp example.jar org.somewhere.MySecondClass
The -cp example.jar puts all of the classes within the jar on the class path and the second argument org.somewhere.MySecondClass gives the class at which execution should begin. This second argument would have to be within the jar since specifying a classpath overrides the default (which is just the current directory). In this case, java ignores any Main-Class specified in the MANIFEST.MF file of the jar (if one even is specified).
Multiple jar files as well as directories of java files not in a jar can be specified by putting colons between them. So,
java -jar example.jar:. MyClass
could launch MyClass from the current directory, but place example.jar on the classpath so that MyClass could create instances of whatever classes are available within example.jar.

How to execute a program within a Jar file

Soo my problem is, that I made some kind of launcher and wrote a method that is being called if you click on the "play" button.
private void PlayButtonActionPerformed(java.awt.event.ActionEvent evt) {
try
{
new ProcessBuilder("src/calc.exe").start();
}
catch (IOException ex)
{
Logger.getLogger(Launcher.class.getName()).log(Level.SEVERE, null, ex);
}
}
The file that is being executed is just a copy of the calculator from Windows and
is in the src folder of my project. (Path is "src/calc.exe")
Everything works fine AS LONG as I don't compile my netbeans project file into a JAR file.
If I run the JAR file and click on the play button - nothing happens.
I really hope you can tell me how to fix this.
(P.S.: calc.exe is not always the name of the program to be run. The filename is determined by an .ini.
calc.exe is only used to test the program.)
First, some context:
A JAR file is an archive, a package (compressed or not) that contains Java bytecode and other resources that can be consumed from inside a JVM.
An EXE file is executable binary file that can only be understandable by Windows/MS-DOS family OSs.
When you run your program without packaging it into a JAR file, all resources (the class file and the executable) are accessible from the OS. Windows will launch the JVM and from inside there you, by means of the ProcessBuilder, instruct the OS to invoke an executable file accessible in a path which is relative to the class performing the execution instruction. Until there, everything is fine and as you said, it works.
However, when you pack your Java class and the executable file in a JAR and invoke the JAR, its contents are no longer accessible for the OS. What is happening is that the OS will launch the JVM and it will process the JAR file to find the executable class (the one in which you invoke the ProcessBuilder). From that class file you now instruct the OS to launch an executable which is in a path relative to the JAR file instead of being relative to the class file performing the invoke instruction. Since the EXE is inside the JAR file instead of being relative to it, execution fails because it can't find the executable.
This is that way because the OS won't look inside the JAR file for a specific file, for the OS the JAR file is just that, a file, not a folder so it will ignore its contents.
So, the conclusion is that, since you are invoking the OS to perform a specific operation in another file, just must place that file outside the JAR and in a relative path to that JAR.
If for some reason you insist on packaging your EXE inside the JAR, then you need to extract it outside the JAR before invoking the ProcessBuilder to a temporary folder and invoke the ProcessBuilder using that new path.
This is sort of a touchy subject.
Whoever commented that JARs are not able to do this is wrong. To the contrary, it is applets that do not have such a permission unless they are signed and validated by the author through Oracle.
You said that it all works fine unless you put it in a JAR. That is probably because of your URI being relative to the Windows filesystem.
The way to usually get the file regardless of the packaging around the reference is to do something like this:
MainClass.class.getResourceAsStream(file);
The static getResourceAsStream will parse the available relative and absolute paths, and if you put your "src/calc.exe" here, it should work.
Another suggestion is to thread the process opening. If you have the program as a single thread, the Java program will hang until the external process is gone and cleaned up.

creating an executable jar file with ant which includes the build.xml file

I am trying to use ant to build an application, run the application's main() method, run junit tests, and package everything in a jar file (source+build+libraries+build.xml). The classes include a runner class with a main() method entry point.
The objective however is to inlcude all libraries used, like junit.jar, and the ant build.xml itself.
I was wondering if there is a way for the executable jar file, to run selected targets of the ant build file itslef, instead of just the main() method. Obviously I wouldn't need to run the compile targets again, but only the main() method (the java element in my run target) and the junit target. Is that possible?
Many thanks in advance for the insight!
"Executable jar" is not what you think it is. It allows you pack all your classes together (you can add source to it as well though I see little point in that) and declare a main class using Main-Class attribute in the jar manifest. Details are here.
You can then launch that jar using "java -jar my.jar" command line which would invoke main() method of the class you've specified. You can also specify classpath via Class-Path attribute in the manifest file that can point to other jars needed by your application. That DOES NOT MEAN those jars are archived within your jar; in fact if you were to do that, JVM won't be able to load classes from those jars unless you were to take special precautions and write a custom classloader.

Categories