Notes on creating a Java "jar" file for an application


If you have an appliation that you want to package so that it can be executed using a command like:

        java -jar myjarfile.jar arg1 arg2

you will need to create the ".jar" file properly. This means that the class containing the main method must be identified and that you have included any necessary support ".jar" files. You must also include a class path.

Sun Microsystems provides documentation on their jar program and the jar file format:

Here is a summary:

In this example, I have four class files that I want to package into the Jar:

DocumentFactory.class
ParserFactory.class
ParserFactory$LocalErrorHandler.class
SplitEntityCreate.class

The class that contains the public static void main( String argv[] ) method is in SplitEntityCreate.

In addition to these classes there are support "jar" files that are needed. Note that when the -jar option is given to java, it will override the local CLASSPATH environment variable. Nor may the support "jar" files be available on the system you execute your application jar. So you need to provide the support "jar" files in your application "jar".

This example application uses three Xerces "jar" files from the Apache project:

xercesImpl.jar
xmlParserAPIs.jar
xmlparserv2.jar

One way to create an executable "jar" file is to copy the class file and the support jar files in a jar build directory. You also need to create a manifest file for the "jar" which I'll cover below. So for this example, the jar build directory would contain:

DocumentFactory.class
ParserFactory.class
ParserFactory$LocalErrorHandler.class
SplitEntityCreate.class

xercesImpl.jar
xmlParserAPIs.jar
xmlparserv2.jar

jar_manifest

The "jar" manifest is an text file that defines, among other things, the class that contains the main method and the class path that will be used when executing the "jar". Here the class path is relative to the "jar" itself, not the local environment. In this example the file jar_manifest contains:

Manifest-Version: 1.0
Main-Class: SplitEntityCreate
Class-Path: xercesImpl.jar xmlParserAPIs.jar xmlParserv2.jar

This defines the class containing the main method as SplitEntityCreate. The class path will be xercesImpl.jar xmlParserAPIs.jar xmlParserv2.jar.

To create the jar file you can use the command:

jar cvfm split.jar jar_manifest DocumentFactory.class ParserFactory.class ParserFactory\$LocalErrorHandler.class SplitEntityCreate.class xercesImpl.jar xmlParserAPIs.jar xmlparserv2.jar

The backslash escape in ParserFactory\$LocalErrorHandler.class stops the Linux/UNIX tcsh shell from interpreting this as a shell veriable.

As the jar on-line man page explains, the arguments cvfm have the following meaning:

c: create a jar archive
v: run in verbose mode
f: use argument that follows as the name for the "jar" archive
m: use the argument that follows the jar archive name as the manifest name

Note that if the arguments were cvmf the manifest name would have been listed before the jar file name:

jar cvmf jar_manifest split.jar ...

For my files, listed above, the jar command printed the following:

added manifest
adding: DocumentFactory.class(in = 3828) (out= 1784)(deflated 53%)
adding: ParserFactory.class(in = 2096) (out= 1049)(deflated 49%)
adding: ParserFactory$LocalErrorHandler.class(in = 1413) (out=
670)(deflated 52%)
adding: SplitEntityCreate.class(in = 8777) (out= 4557)(deflated 48%)
adding: xercesImpl.jar(in = 927669) (out= 819216)(deflated 11%)
adding: xmlParserAPIs.jar(in = 123705) (out= 91673)(deflated 25%)
adding: xmlparserv2.jar(in = 660495) (out= 619207)(deflated 6%)

Postscript

I ran the "jar" that I built above on the system I developed the software on. Then I copied it to a remote system and tried to execute it. Despite the class path defined in the manifest, I seemed to run into class path problems. For example, java reported that it could not find the DOMParser class, even through this class is in the xercesImpl.jar archive and a class path, including xercesImpl.jar was defined in the "jar" manifest.

The source of this problem was not obvious. Perhaps incompatible versions of java. I finally made sure that the CLASSPATH environment variable included the local directory (".") and I unpacked the "jar" file using the command:

jar xvf split.jar

This unpacked the class files and the "jar" files into the local directory. I could then execute the command:

   java -jar split.jar ....

So in summary, I may still be missing something in these notes. If I have, please send me an email (click on the mailbox icon below).

Postscript to the Postscript

Martin kindly sent me a very informative note about the problems of class paths and jar files. It was gratifying to read that I am not alone in having difficulties with getting applications to run for a jar file. It was even more gratifying to get a pointer to a solution. Martin sent me a link to Simon Tuffs web page Deliver Your Java Application in One-JAR!.

Simon Tuffs' web page provides one of the best discussions I've read on the complexities of creating jars, jars and class paths and the jar "manifest". Simon also provides a Java tool, one-jar, for creating application jar files.

Ian Kaplan, February 2005
Updated: July 2007