How to make a Jar File
Update. 15/12/2008 12:12:00 AM. Added trouble shooting section based on my first comment. Updated formatting.
Update. 18/12/2008 10:54:10 AM. Added to the trouble shooting section. Removed the Warning in the section "Run Executable JAR from Explorer (Windows)" - it was wrong!
Jar files provide a way to group (and compress) multiple Java files into one "archive" file. If you write an API made up of hundreds of Java files, it is much easier to distribute and import the API using one jar file than manage directories of Java files. Jar archives can be opened with any archive application like WinZip or WinRar (both for Windows). Rar and zip commands are usually native to Linux distro's without any downloads.
Jar files can also be executed, meaning that a complete Java application can be distributed as a single jar and run from the command line or by double clicking the file in your window manager. This tutorial shows you how.
- Continuation Characters
- Java Files
- How To Use Jar Command
- Non Executable Examples of the Jar Command
- Create An Executable Jar
- Create An Executable Jar with Ant
- Run Executable Jar from Command Line
- Run Executable Jar from Explorer (Windows)
- Quick Trouble Shooting Guide
- Other Resources
Continuation characters
In certain code snippets below, I use the continuation character "\". This enables a single command to be spread across multiple lines.
Bash continuation character (I use Bash/Cygwin/Windows). It means I can copy and paste the four lines below into a Bash terminal and have them executed as one command.
jar cf HelloWorld.jar \ org/bram/helloworld/HelloWorld.class \ org/bram/helloworld/SecondHelloWorld.class \ org/bram/helloworld/ThirdHelloWorld.class
This shows the same code using the Windows-DOS continuation character. It means I can copy and paste the four lines below into a DOS command prompt and have them executed as one command.
jar cf HelloWorld.jar ^ org/bram/helloworld/HelloWorld.class ^ org/bram/helloworld/SecondHelloWorld.class ^ org/bram/helloworld/ThirdHelloWorld.class
Java Files
Gather your Java source. Here is a simple Hello World.
package org.bram.helloworld; import javax.swing.JOptionPane; public class HelloWorld { public static void main (String [] args) { JOptionPane.showMessageDialog(null, "Hello World!"); } }
A quick command line test shows it can be compiled and run ok.
javac org/bram/helloworld/HelloWorld.java java org.bram.helloworld.HelloWorld
I have made a few copies of this file, so I have a few Java files now.
bash3.2 User rbram on host itvw1846 in dir /cygdrive/c/Temp/rbram Mon Nov 12 09:13 AM> javac org/bram/helloworld/*.java bash3.2 User rbram on host itvw1846 in dir /cygdrive/c/Temp/rbram Mon Nov 12 09:13 AM> ls org/bram/helloworld/ . HelloWorld.class SecondHelloWorld.class ThirdHelloWorld.class .. HelloWorld.java SecondHelloWorld.java ThirdHelloWorld.java
How To Use Jar Command
Now that we have the Java source and class files, we should look at the 'jar' command. It is a utility program that can be run from the command line (DOS prompt or bash terminal for example, depending on your OS). Here is how to create a compressed JAR file:
jar cf archive_name.jar files
Let's look at each part of that command line.
- jar - the command to run the jar utility.
- cf - "c" indicates that we wish to create a jar file (as opposed to extracting one, for example) and "f" indicates that we are going to specify a file name, i.e. "archive_name.jar".
- Here is a list of the common options. I triggered the output below by issuing an invalid command to view the usage message.
bash3.2 User rbram on host itvw1846 in dir /cygdrive/c/Temp/rbram Mon Nov 12 09:02 AM> jar invalid Usage: jar {ctxu}[vfm0Mi] [jar-file] [manifest-file] [-C dir] files ... Options: -c create new archive -t list table of contents for archive -x extract named (or all) files from archive -u update existing archive -v generate verbose output on standard output -f specify archive file name -m include manifest information from specified manifest file -0 store only; use no ZIP compression -M do not create a manifest file for the entries -i generate index information for the specified jar files -C change to the specified directory and include the following file If any file is a directory then it is processed recursively. The manifest file name and the archive file name needs to be specified in the same order the 'm' and 'f' flags are specified. Example 1: to archive two class files into an archive called classes.jar: jar cvf classes.jar Foo.class Bar.class Example 2: use an existing manifest file 'mymanifest' and archive all the files in the foo/ directory into 'classes.jar': jar cvfm classes.jar mymanifest -C foo/ .
Non Executable Examples of the Jar Command
So, I have a Java application consisting of three source files that I wish to distribute:
org/bram/helloworld/HelloWorld.java org/bram/helloworld/SecondHelloWorld.java org/bram/helloworld/ThirdHelloWorld.java
I also want to call my JAR file HelloWorld.jar. To make a JAR file with just HelloWorld.java:
jar cf HelloWorld.jar org/bram/helloworld/HelloWorld.java org/bram/helloworld/HelloWorld.class
This creates the following Jar
We can't run this file - it is not executable. All we have done is compress multiple Java files (a source and a class file) into a single artefact that you can distribute and include in other Java applications. For example, if someone wanted the magnificent HelloWorld functionality, they can include HelloWorld.jar in their project's classpath and use it in their own Java files.
import org.bram.helloworld.HelloWorld; ... // Magnificent HelloWorld popup. HelloWorld.main();
Here is how you can make a jar with all three files listed separately.
jar cf HelloWorld.jar \ org/bram/helloworld/HelloWorld.class \ org/bram/helloworld/SecondHelloWorld.class \ org/bram/helloworld/ThirdHelloWorld.class
We could do the same thing using a pattern match.
jar cf HelloWorld.jar \ org/bram/helloworld/*.class
Of course, we want to include the source files too.
jar cf HelloWorld.jar \ org/bram/helloworld/*.*
It creates the following jar file.
Note that in this example, the source files are in the same directory as the class files are. This is a 'convenience' so that I have all the files in one place. It is common for publicly released API's to have two jars: one with the class files and a different jar with source files.
Create An Executable JAR
In the screen shots above, you may have noticed the manifest files. The manifest file holds information about the jar that Java can use, such as the name of a Java class that should be run when if the jar file is executed. See Other Resources for some more detail about manifest files.
Create a text file that lists the "main" class, which references a Java class with a main method that will be run when the jar is executed. I create a text file called "manifest.txt" with the following contents.
Main-Class: org.bram.helloworld.HelloWorld
Note 1. This file MUST end with a blank line i.e. the text file I created had two lines - the line above plus a blank line.
Note 2. You must specify the fully qualified name of the class i.e. package + Java class name. You do not use the class file extension (.class) or source file extension (.java).
I can run the jar utility with a new option "m" and the name of the manifest file. This is the command I use.
jar cmf manifest.txt \ HelloWorld.jar \ org/bram/helloworld/*.java \ org/bram/helloworld/*.class
This is the result.
Create An Executable JAR with Ant
Making jar files with a command line is easy for small projects. What happens when you need to jar an API that does have hundreds of files in different packages? The command line would start to get very large and unwieldly. You could put it into a .bat file (DOS) or .sh (*nix), but you still have the problem with the list of files getting large and hard to maintain.
A much better solution is to use an Ant build file. The advantage is that it lets you specify the contents in terms of directories, so it is much easier to maintain and repeat each time a new build is required.
The following would be saved as build.xml to the same base directory as the "org" folder is stored in.
<?xml version="1.0"?> <project name="HelloWorld" default="buildJar" basedir="."> <target name="buildJar"> <delete file="${basedir}/HelloWorld.jar" failonerror="false" /> <jar destfile="${basedir}/HelloWorld.jar" basedir="." excludes="**/*.bak manifest.txt build.xml"> <manifest> <attribute name="Built-By" value="${user.name}"/> <attribute name="Main-Class" value="org.bram.helloworld.HelloWorld"/> </manifest> </jar> </target> </project>
To run this, simply run the command "ant" from the same base directory.
Run Executable JAR from Command Line
I can run it from the command line like this.
java -jar HelloWorld.jar
Here is the result.
Run Executable JAR from Explorer (Windows)
Tested on Windows XP If you find this is different on your version of Windows, email me at robertmarkbram AT gmail dot com and let me know.
Within Windows Explorer, you can double click on a jar file and have it automatically execute the main class. This makes jar files a suitable alternative to exe files - very handy for GUI applications distributed as jar files.
There are two caveats. Firstly, you need to have a JRE (or JDK) installed on the machine that will run the jar. Secondly, an association must be set up that tells Windows that .jar files should be run be run by "javaw.exe", which is part of any JRE or JDK installation.
Open Windows Explorer and select "Tools | Folder Options | File Types". You might see that jars are set up by default when you installed Java, as the below screen shot shows. Click on "Advanced" to check it out further.
Clicking "Advanced" shows you the "Edit File Type" dialog below. Click "Edit" on the "open" action.
This is the dialog showing the "open" action. Note the "Application used to perform action".
For me, that value is as below.
"c:\IBM\SDP70\jdk\bin\javaw.exe" -jar "%1" %*
If you don't see the mapping, click "New" in the "Folder Options" dialog. Type "jar" as the "File Extension" and press "OK". Then you can click "Advanced" on the jar association and set up the "open" action as per the screen shots above.
Double clicking on the file executes it.
Quick Trouble Shooting Guide
- You can open jar files with winzip to see what is inside them.
- You can have .java and .class files in a jar.
- You must have a .class file with a main method that is referenced in the manifest in order to create an executable jar.
- Look for error messages - i.e. an error dialog. If you see a command prompt pop up and disappear too quickly for you to see what was in it, try running the jar from the commandline using "javaw.exe -jar" - then you will see the error message in the command window
- Failed to load Main-Class manifest attribute. Your manifest file doesn't specify the Main-Class attribute. See the create an executable jar section.
- java.io.IOException: "invalid header field". Did you write your manifest file in Word or WordPad? This might be caused by illegal characters being in this file: try creating and saving the file in a text editor. Found this suggested in a sun forum post.
- I run the Jar from the command line and see the output ok, but when I double click on my jar file I see no output - no errors either, but still, no output! I am outputting text using System.out.println("") statements. The reason you can't see anything when you double click on the jar file is because System.out.println("") outputs to a console: you have no console, since you didn't launch the application from one, and a console isn't automatically created for you when you launch a file with a double click.
If you want to see output by double clicking, you can try aJOptionPane
- an easy to use GUI component. Try this: javax.swing.JOptionPane.showMessageDialog(null, "My Message");. - Could not find the main class. Program will exit. There are a few possibilities.
- Check the class name listed in your manifest file.
- Is the class spelt correctly?
- Is the package correct?
- You can use slashes instead of periods e.g.
my/test/HelloWorld
ormy.test.HelloWorld
will work, so this isn't an issue. - Have you mistakenly ended the class name with
.class
or.java
? If so, remove it. - Check your Jar File Types setting (for Windows).
- Have you mistakenly left out some crucial spaces in the arguments list? Make sure you have spaces as per the red highlighted spaces in the following
"C:\Program Files\Java\j2re1.4.2_05\bin\javaw.exe" -jar "%1" %*
- XXX is not recognized as an internal or external command, operable program or batch file. In short, Java's bin dir isn't on your PATh. See my other blog post on this issue.
- Are you using JDK 1.4 or lower with spaces in the path? E.g.
C:\Program Files\Java\j2re1.4.2_05\bin\javaw.exe
might need to be shortened using the DOS short form to this instead:"C:\Progra~1\Java\j2re1.4.2_05\bin\javaw.exe
Other Resources
- Sun's overview of jar command.
- Sun's JAR File Specification.
- Sun's Understanding the Manifest.
- Sun Trail: Packaging Programs in JAR Files.
- Roedy Green's Java Glossary "jar" entry.
- A very comprehensive guide written by Cjard on Code Guru's forums: TIP: Packaging your Java applications for other people
- My original tutorial on this subject. I made this when I was at Monash Uni. I don't control this page anymore; frankly it surprises me that this page is still up! Here is the home page for my work at Monash all that long time ago.
Comments
- you can open jar files with winzip to see what is inside them.
- you can have .java and .class files in a jar.
- you must have a .class file with a main method that is referenced in the manifest in order to create an executable jar.
- look for error messages - i.e. an error dialog. If you see a command prompt pop up and disappear too quickly for you to see what was in it, try running the jar from the commandline using "javaw.exe -jar" - then you will see the error message in the command window
Rob
:)
Interesting Javascript Slideshow tutorial your nick links to, I like that a lot. I did my own, much simpler version for my Mum's site. Might need to upgrade it. :)