JAR Files

A JAR file is similar to a tar file in that it constitutes an archive of Java class files and source files. JAR files are created with the jar command and the jar command takes many of the same arguments as tar. The jar command automatically performs compression on your class files using the ZIP file format.

You can use the jar command to package all the class files for your application into a single file. If you also tell the jar command the main class to access within the jar file, then you can treat the jar file as a pseudo-object file. Finally, if you want, you can also include your source files in the jar file, although normally you would not do so. In this course we want you to submit both your class and source files, so you will be including the source files in your jar file.

The following table, which I copied from Sun's tutorial website on the jar command, shows the most common uses of the jar command:

OperationCommand
To create a JAR file jar cf jar-file input-file(s)
To view the contents of a JAR file jar tf jar-file
To extract the contents of a JAR file jar xf jar-file
To run an application packaged as a JAR file (requires the Main-class manifest header)
java -jar app.jar

Specifying an Application's Entry Point

You can tell java how to find the entry point within your jar file by creating a manifest file. A manifest file can have any name you choose although manifest.txt is a commonly chosen one. A manifest file should contain the following single statement:

Main-Class: classname

Main-Class is a required keyword and classname is the name of the class that contains your application's main method.

Here is an example manifest file for an application whose main class is SalaryList:

Main-Class: SalaryList

If you are using packages, then you need to fully qualify the class name. Here is an example manifest file for an application whose main class is named LexDriver and which is contained in a package named formula:

Main-Class: formula.LexDriver

Creating a Jar File that Contains a Manifest

When you create your jar file, you can include m as a command line option. This option causes java to use the file specified after the m flag as the manifest file. For example, if the above file is named manifest.txt and your files are in a directory named formula, you could create your jar file with the following command:

jar cmf manifest.txt formula.jar formula

Note that you can specify all of your flags before specifying the files. The files should be specified in the same order as the flags. The name of the jar file does not have to be the same as your main class.

A Simpler Way to Specify the Application Entry Point

The jar tool has a -e flag that allows you to specify the application's entry point without creating a manifest file. For example the command:

jar cfe Salary.jar SalaryList *.class
will automatically create a manifest file that contains SalaryList as the application entry point.

Executing a Jar File with an Application Entry Point

In order to execute a jar file that has an entry point specified, invoke java with the -jar option and the jar file's name. For example:

java -jar formula.jar

Some Example Jar Creation Commands

Here are some sample commands for creating jar files. All of the example commands assume that the manifest file is named manifest.txt. If you choose to use a different name for the manifest file, then change manifest.txt to whatever file name you choose.

  1. You are in the directory that contains the .class files, and you only want to include the .class files.
    jar cmf manifest.txt foo.jar *.class
    
  2. You are in the directory that contains the .class files, and you want to include both the .java and the .class files.
    jar cmf manifest.txt foo.jar *.class *.java
    
  3. You are in the directory that contains the .class files, and you only want to include the .class files associated with the class foo.
    jar cmf manifest.txt foo.jar foo*.class
    
    This command will scoop up both the foo.class file and any nested classes declared in the foo class.

  4. Your files are in the hw1 directory and you are in hw1's parent directory. You want to include both the .class files and .java files associated with the class foo:
    jar cmf hw1/manifest.txt foo.jar hw1/foo*.class hw1/foo.java
    
  5. Your files are in a package named silhouette and you are in silhouette's parent directory. You want to include both the .class and the .java files for silhouette. If you are jarring up a package, then make sure that you are in the parent directory, since it is vital that the entire directory tree for the package end up in the jar file:
    jar cmf silhouette/manifest.txt silhouette.jar silhouette
    

Warnings about Using Jar and Manifest Files

  1. The manifest file must end with a new line or carriage return. The last line will not be parsed properly if it does not end with a new line or carriage return.

  2. Normally you will jar up a directory tree and the directory tree will contain all the files needed for your application. However, should you wish to include files from other packages, then you can use the -C flag to change to these packages' parent directory and then grab the packages directoriess. For example, suppose that you are jarring up the foo.class, and that foo creates an instance of play.Hello, which can be found in /Users/bvz/cs102/play/Hello.class. If you try to type:
    jar cmf manifest.txt foo.jar foo.class /Users/bvz/cs102/play/Hello.class
    
    then your jar file won't work properly, because Hello.class will get included in your jar file as /Users/bvz/cs102/play/Hello.class. If instead you try to type:
    jar cmf manifest.txt foo.jar foo.class /Users/bvz/cs102/play/
    
    then the play directory will be represented in your jar file as /Users/bvz/cs102/play, rather than as play and java will not be able to locate the Hello.class file. Instead you should type:
    jar cmf manifest.txt foo.jar foo.class -C /Users/bvz/cs102/ play/Hello.class
    
    The -C flag causes the jar command to "cd" to the /Users/bvz/cs102/ directory and then grab the play/Hello.class (it will create a directory for play in your jar file and store Hello.class in the play directory). The jar file will now contain foo.class and play/Hello.class, which is what you want.

  3. If you use the -jar option, the java interpreter expects all user classes to be bundled in either the jar file or in jar files that are referenced by the manifest file's Class-Path parameter. (The specific statement can be found in the documentation for java's -jar flag and reads "When you use this option, the JAR file is the source of all user classes, and other user class path settings are ignored.") The Class-Path parameter may only contain references to jar files and the jar files must be in directories local to the machine on which the jar file is being run, not in the jar file itself. The Class-Path parameter may not specify directories in either the jar file itself, or on the local machine that contain class files. If you want classes in your jar file to access external class files that simply exist in a directory, such as for example, java_cup/runtime classes, then you are out of luck and cannot use the -jar option with java.

  4. While you are allowed to embed .jar files within an outer .jar file, you will not be able to load this embedded .jar file into your program without writing custom code. The Class-Path parameter described in the previous bullet point cannot be used to load embedded .jar files into your program. I personally have never seen the custom code required to load an embedded jar file into your program but you could probably google it.


Where to Find More Information about Jar Files

You can find more information about jar files and manifest files here.