JAR Files

 


 

Overview

The Java Archive (JAR) file format enables you to bundle multiple files into a single archive file. Typically a JAR file will contain the class files and auxiliary resources associated with applets and apps. JAR files are packaged with the ZIP file format, so you can use them for "ZIP-like" tasks such as lossless data compression, archiving, decompression, and archive unpacking.

The following table summarizes common JAR-file operations:

Operation Command
Create a JAR file jar cf jar-file input-file(s)
View contents jar tf jar-file
Extract contents jar xf jar-file
Extract specific files jar xf jar-file archived-file(s)
Run an app packaged as a JAR file jre -cp app.jar MainClass
Run an app packaged as a JAR file java -jar app.jar
Invoke an applet packaged as a JAR file <applet
code=AppletClassName.class
archive="JarFileName.jar"
width=width height=height>
</applet>

 

 

Additional References

The documenation for the Java Development Kit includes reference pages for the Jar tool:

 


 

Creating a JAR File

The basic format of the command for creating a JAR file is:

jar cf jar-file input-file(s)
Let's look at the options and arguments used in this command:

  • The c option indicates that you want to create a JAR file.
  • The f option indicates that you want the output to go to a file rather than to stdout.
  • jar-file is the name that you want the resulting JAR file to have. You can use any filename for a JAR file. By convention, JAR filenames are given a .jar extension, though this is not required.
  • The input-file(s) argument is a space-separated list of one or more files that you want to be placed in your JAR file. The input-file(s) argument can contain the wildcard * symbol. If any of the "input-files" are directories, the contents of those directories are added to the JAR archive recursively.

The c and f options can appear in either order, but there must not be any space between them.

This command will generate a compressed JAR file and place it in the current directory. The command will also generate a default manifest file for the JAR archive.

You can add any of these additional options to the cf options of the basic command:

OptionDescription
v Produces verbose output on stderr (in version 1.1) or stdout (in version 1.2) while the JAR file is being built. The verbose output tells you the name of each file as it's added to the JAR file.
0 (zero) Indicates that you don't want the JAR file to be compressed.
M Indicates that the default manifest file should not be produced.
m Used to include manifest information from an existing manifest file. The format for using this option is:

    jar cmf existing-manifest jar-file input-file(s)
    
-C To change directories during execution of the command. Version 1.2 only. See below for an example.

In version 1.1, the JAR-file format supports only ASCII filenames. Version 1.2 adds support for UTF8-encoded names.

 

 

An Example

Let's look at an example. The JDK demos include a simple TicTacToe applet. This demo contains a bytecode class file, audio files, and images all housed in a directory called TicTacToe having this structure:

The audio and images subdirectories contain sound files and GIF images used by the applet.

To package this demo into a single JAR file named TicTacToe.jar, you would run this command from inside the TicTacToe directory:

jar cvf TicTacToe.jar TicTacToe.class audio images
The audio and images arguments represent directories, so the Jar tool will recursively place them and their contents in the JAR file. The generated JAR file TicTacToe.jar will be placed in the current directory. Because the command used the v option for verbose output, you'd see something similar to this output when you run the command:

adding: TicTacToe.class (in=3825) (out=2222) (deflated 41%)
adding: audio/ (in=0) (out=0) (stored 0%)
adding: audio/beep.au (in=4032) (out=3572) (deflated 11%)
adding: audio/ding.au (in=2566) (out=2055) (deflated 19%)
adding: audio/return.au (in=6558) (out=4401) (deflated 32%)
adding: audio/yahoo1.au (in=7834) (out=6985) (deflated 10%)
adding: audio/yahoo2.au (in=7463) (out=4607) (deflated 38%)
adding: images/ (in=0) (out=0) (stored 0%)
adding: images/cross.gif (in=157) (out=160) (deflated -1%)
adding: images/not.gif (in=158) (out=161) (deflated -1%)

You can see from this output that the JAR file TicTacToe.jar is compressed. The Jar tool compresses files by default. You can turn off the compression feature by using the 0 (zero) option, so that the command would look like:

jar cvf0 TicTacToe.jar TicTacToe.class audio images

You might want to avoid compression, for example, to increase the speed with which a JAR file could be loaded by a browser. Uncompressed JAR files can generally be loaded more quickly than compressed files because the need to decompress the files during loading is eliminated. However, there's a tradeoff in that download time over a network may be longer for larger, uncompressed files.

The Jar tool will accept arguments that use the wildcard * symbol. As long as there weren't any unwanted files in the TicTacToe directory, you could have used this alternative command to construct the JAR file:

jar cvf TicTacToe.jar *

Though the verbose output doesn't indicate it, the Jar tool automatically adds a manifest file to the JAR archive with pathname META-INF/MANIFEST.MF.

In the above example, the files in the archive retained their relative pathnames and directory structure. The Jar tool in version 1.2 of the Java Development Kit provides the -C option that you can use to create a JAR file in which the relative paths of the archived files are not preserved. It's modeled after GZIP's -C option.

As an example, suppose you wanted put audio files and gif images used by the TicTacToe demo into a JAR file, and that you wanted all the files to be on the top level, with no directory hierarchy. You could accomplish that by issuing this command from the parent directory of the images and audio directories:

jar cf ImageAudio.jar -C images . -C audio .
The -C images part of this command directs the Jar tool to go to the images directory, and the . following -C images directs the Jar tool to archive all the contents of that directory. The -C audio . part of the command then does the same with the audio directory. The resulting JAR file would have this table of contents:

META-INF/MANIFEST.MF
cross.gif
not.gif
beep.au
ding.au
return.au
yahoo1.au
yahoo2.au
By contrast, suppose that you used a command that didn't employ the -C option:

jar cf ImageAudio.jar images audio
The resulting JAR file would have this table of contents:

META-INF/MANIFEST.MF
images/cross.gif
images/not.gif
audio/beep.au
audio/ding.au
audio/return.au
audio/yahoo1.au
audio/yahoo2.au

 


 

Viewing the Contents of a JAR File

The basic format of the command for viewing the contents of a JAR file is:

jar tf jar-file
Let's look at the options and argument used in this command:

  • The t option indicates that you want to view the table of contents of the JAR file.
  • The f option indicates that the JAR file whose contents are to be viewed is specified on the command line. Without the f option, the Jar tool would expect a filename on stdin.
  • The jar-file argument is the filename (or path and filename) of the JAR file whose contents you want to view.

The t and f options can appear in either order, but there must not be any space between them.

This command will display the JAR file's table of contents to stdout.

You can optionally add the verbose option, v, to produce additional information about file sizes and last-modified dates in the output.

 

 

An Example

Let's use the Jar tool to list the contents of the TicTacToe.jar file we created in the previous section:

jar tf TicTacToe.jar

This command displays the contents of the JAR file to stdout:

META-INF/MANIFEST.MF
TicTacToe.class
audio/
audio/beep.au
audio/ding.au
audio/return.au
audio/yahoo1.au
audio/yahoo2.au
images/
images/cross.gif
images/not.gif

The JAR file contains the TicTacToe class file and the audio and images directory, as expected. The output also shows that JAR file contains a manifest file, META-INF/MANIFEST.MF, which was automatically placed in the archive by the JAR tool.

All pathnames are displayed with forward slashes, regardless of the platform or operating system you're using. Paths in JAR files are always relative; you'll never see a path beginning with C:, for example.

The JAR tool will display additional information if you use the v option:

jar tvf TicTacToe.jar

For example, the verbose output for the TicTacToe JAR file would look similar to this:

 256 Mon Apr 20 10:50:28 PDT 1998 META-INF/MANIFEST.MF
3885 Mon Apr 20 10:49:50 PDT 1998 TicTacToe.class
   0 Wed Apr 15 16:39:32 PDT 1998 audio/
4032 Wed Apr 15 16:39:32 PDT 1998 audio/beep.au
2566 Wed Apr 15 16:39:32 PDT 1998 audio/ding.au
6558 Wed Apr 15 16:39:32 PDT 1998 audio/return.au
7834 Wed Apr 15 16:39:32 PDT 1998 audio/yahoo1.au
7463 Wed Apr 15 16:39:32 PDT 1998 audio/yahoo2.au
   0 Wed Apr 15 16:39:44 PDT 1998 images/
 157 Wed Apr 15 16:39:44 PDT 1998 images/cross.gif
 158 Wed Apr 15 16:39:44 PDT 1998 images/not.gif

 


 

Extracting the Contents of a JAR File

The basic command to use for extracting the contents of a JAR file is:

jar xf jar-file [archived-file(s)]

Let's look at the options and arguments in this command:

  • The x option indicates that you want to extract files from the JAR archive.
  • The f options indicates that the JAR file from which files are to be extracted is specified on the command line, rather than through stdin.
  • The jar-file argument is the filename (or path and filename) of the JAR file from which to extract files.
  • archived-file(s) is an optional argument consisting of a space-separated list of the files to be extracted from the archive. If this argument is not present, the Jar tool will extract all the files in the archive.

As usual, the order in which the x and f options appear in the command doesn't matter, but there must not be a space between them.

When extracting files, the Jar tool makes copies of the desired files and writes them to the current directory, reproducing the directory structure that the files have in the archive. The original JAR file remains unchanged.

When it extracts files, the Jar tool will overwrite any existing files having the same pathname as the extracted files.

 

 

An Example

Let's extract some files from the TicTacToe JAR file we've been using in previous sections. Recall that the contents of TicTacToe.jar are:

META-INF/MANIFEST.MF
TicTacToe.class
audio/
audio/beep.au
audio/ding.au
audio/return.au
audio/yahoo1.au
audio/yahoo2.au
images/
images/cross.gif
images/not.gif

Suppose you want to extract the TicTacToe class file and the cross.gif image file. To do so, you can use this command:

jar xf TicTacToe.jar TicTacToe.class images/cross.gif

This command does two things:

  • It places a copy of TicTacToe.class in the current directory.
  • It creates the directory images, if it doesn't already exist, and places a copy of cross.gif within it.

The original TicTacToe JAR file remains unchanged.

As many files as desired can be extracted from the JAR file in the same way. When the command doesn't specify which files to extract, the Jar tool extracts all files in the archive. For example, you can extract all the files in the TicTacToe archive by using this command:

jar xf TicTacToe.jar

 


 

Modifying a Manifest File

You can modify the contents of a JAR file in a couple of ways. One method, available in both versions 1.1 and 1.2 of the Jar tool, uses the m command-line option to add custom information to the manifest during creation of a JAR file. The m option is described in this section.

Version 1.2 of the Jar tool also provides a u option which you can used to update the contents of an existing JAR file, including its manifest. The u option is covered in the section called Updating a JAR File.

The Jar tool automatically puts a default manifest with pathname META-INF/MANIFEST.MF into any JAR file you create. You can enable special JAR file functionality, such as package sealing, by modifying the default manifest. Typically, this involves adding special-purpose headers to the manifest that allow the JAR file to perform a particular desired function.

The Jar tool's m option allows you to add information to the default manifest during creation of a JAR file. You must first prepare a text file containing the information you wish to add to the default manifest. You can then use the Jar tool's m option to add the information in your file to the default manifest.

The basic command has this format:

jar cmf manifest-addition jar-file input-file(s)
Let's look at the options and arguments used in this command:

  • The c option indicates that you want to create a JAR file.
  • The m option indicates that you want to merge information from an existing manifest file into the manifest file of the JAR file you're creating.
  • The f option indicates that you want the output to go to a file (the JAR file you're creating) rather than to stdout.
  • manifest-addition is the name (or path and name) of the existing text file whose contents you want included in the JAR file's manifest.
  • jar-file is the name that you want the resulting JAR file to have.
  • The input-file(s) argument is a space-separated list of one or more files that you want to be placed in your JAR file.

The c, m, and f options can appear in any order, but there must not be any whitespace between them.

 

 

An Example

In version 1.2 of the Java platform, packages within JAR files can be optionally sealed, which means that all classes defined in that package must be archived in the same JAR file. You might want to seal a package, for example, to ensure version consistency among the classes in your software.

A package can be sealed by adding the Sealed header beneath the header naming the package that's to be sealed.:

Name: myCompany/myPackage/
Sealed: true

The default manifest created by the Jar tool does not contain any Sealed headers, of course, because packages are not sealed by default. To seal a package, you therefore have to add the Sealed header yourself. To insert the Sealed header in a JAR file's manifest, you first need to write a text file containing the appropriate headers. The file you write doesn't have to be a complete manifest file; it can contain just enough information for the Jar tool to know where and what information to merge into the default manifest.

Let's suppose, for example, that your JAR file is to contain these four packages:

myCompany/firstPackage/
myCompany/secondPackage/
myCompany/thirdPackage/
myCompany/fourthPackage/
To seal firstPackage and thirdPackage, you would write a text file with contents that look like this:

Name: myCompany/firstPackage/
Sealed: true

Name: myCompany/thirdPackage/
Sealed: true

Warning: The text 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.
Note that the package names end with a "/". This file contains the information that needs to be added to the default manifest to seal the desired packages. Each Sealed header is immediately preceeded by a Name header that indicates which package is to be sealed.

Let's suppose that:

  • you named your text file sealInfo
  • the JAR file you want to create will have the name myJar.jar
  • the current directory is the parent directory of myCompany

You would create the JAR file with this command:

jar cmf sealInfo myJar.jar myCompany

The precise look of the resulting manifest file in myJar.jar would depend upon whether you were using version 1.1 or version 1.2 of the Java Development Kit. In either case, the Sealed header would be included for firstPackage and thirdPackage. If you were using the version 1.2 Jar tool, the manifest would look like this:

Manifest-Version: 1.0

Name: myCompany/firstPackage/
Sealed: true

Name: myCompany/thirdPackage/
Sealed: true
Only the first line, Manifest-Version: 1.0, is part of the default manifest. The other lines are in the manifest because you added them when the Jar file was created by using the m option.

 


 

Updating a JAR File

The Jar tool in version 1.2 of the Java Development Kit provides a u option which you can use to update the contents of an existing JAR file by modifying its manifest or by adding files.

The basic command for adding files has this format:

jar uf jar-file input-file(s)

In this command:

  • The u option indicates that you want to update an existing JAR file.
  • The f option indicates that the JAR file to update is specified on the command line. If the f option is not present, the Jar tool will expect a JAR filename on stdin.
  • jar-file is the existing JAR file that's to be updated.
  • input-file(s) is a space-deliminated list of one or more files that you want to add to the Jar file.

Any files already in the archive having the same pathname as a file being added will be overwritten.

As when creating a new JAR file, you can optionally use the -C option to indicate a change of directory.

You can combine the u option with the m option to update an existing JAR file's manifest:

jar umf manifest jar-file

In this command:

  • The m option indicates that you want to update the JAR file's manifest.
  • manifest is the manifest whose contents you want to merge into the manifest of the existing JAR file.

 

 

Examples

Recall that TicTacToe.jar has these contents:

META-INF/MANIFEST.MF
TicTacToe.class
audio/
audio/beep.au
audio/ding.au
audio/return.au
audio/yahoo1.au
audio/yahoo2.au
images/
images/cross.gif
images/not.gif

Suppose that you want to add the file images/new.gif to the JAR file. You could accomplish that by issuing this command from the parent directory of the images directory:

jar uf TicTacToe.jar images/new.gif

The revised JAR file would have this table of contents:

META-INF/MANIFEST.MF
TicTacToe.class
audio/
audio/beep.au
audio/ding.au
audio/return.au
audio/yahoo1.au
audio/yahoo2.au
images/
images/cross.gif
images/not.gif
images/new.gif

You can use the -C option to "change directories" during execution of the command. For example:

jar uf TicTacToe.jar -C images new.gif
This command would change to the images directory before adding new.gif to the JAR file. The images directory would not be included in the pathname of new.gif when it's added to the archive, resulting in a table of contents that looks like this:

META-INF/MANIFEST.MF
TicTacToe.class
audio/
audio/beep.au
audio/ding.au
audio/return.au
audio/yahoo1.au
audio/yahoo2.au
images/
images/cross.gif
images/not.gif
new.gif

As a final example, suppose you want to modify the default manifest of TicTacToe.jar by adding some version and vendor information. (Version and vendor information is contained in special headers that you can add to a JAR file's manifest. You would first prepare a text file containing the headers that you wish to add to the default manifest. Your text file might consist of this information, for example:

Name: TicTacToe.class
Implementation-Title: "TicTacToe demo" 
Implementation-Version: "build57"
Implementation-Vendor: "Sun Microsystems, Inc."

If the file containing this information was called versionInfo, you would add the information to the manifest in TicTacToe.jar by using this command:

jar umf versionInfo TicTacToe.jar

After running this command, TicTacToe.jar's manifest would contain the information from your versionInfo file.

 


 

Running JAR-Packaged Software

Now that you've learned how to create JAR files, how do you actually run the code that you've packaged? Consider these three scenarios:

  • Your JAR file contains an applet that is to be run inside a browser.
  • Your JAR file contains an application that is to be invoked from the command line.
  • Your JAR file contains code that you want to use as an extension.

This section will cover the first two situations. A separate trail in the tutorial on the extension mechanism covers the use of JAR files as extensions.

 

 

Applets Packaged in JAR Files

To invoke any applet from an HTML file for running inside a browser, you need to use the APPLET tag. (See the Writing Applets trail for information on applets.) If the applet is bundled as a JAR file, the only thing you need to do differently is to use the ARCHIVE parameter to specify the relative path to the JAR file.

As an example, let's use (again!) the TicTacToe demo applet that ships with the Java Development Kit. The APPLET tag in the HTML file that calls the demo looks like this:

<applet code=TicTacToe.class 
        width=120 height=120>
</applet>

If the TicTacToe demo were packaged in a JAR file named TicTacToe.jar, you could modify the APPLET tag with the simple addition of an ARCHIVE parameter:

<applet code=TicTacToe.class 
        archive="TicTacToe.jar"
        width=120 height=120>
</applet>

The ARCHIVE parameter specifies the relative path to the JAR file that contains TicTacToe.class. This example assumes that the JAR file and the HTML file are in the same directory. If they're not, you would need to include the JAR file's relative path in the ARCHIVE parameter's value. For example, if the JAR file was one directory below the HTML file in a directory called applets, the APPLET tag would look like this:

<applet code=TicTacToe.class 
        archive="applets/TicTacToe.jar"
        width=120 height=120>
</applet>

 

 

Applications Packaged in JAR Files - 1.1 platform

You can run applications that are bundled as JAR files by using the JDK 1.1 jre tool:

jre -cp app.jar MainClass

In version 1.1 of the JDK software, the -cp option prepends the app.jar file to the system classpath. MainClass identifies the class within the JAR file that is the application's entry point. (Recall that in an application, one of the classes must have a method with the signature public static void main(String[] args) that serves as entry or starting point for the application.)

 

 

JAR Files as Applications - 1.2 platform only

In version 1.2 of the JDK software, you can run JAR-packaged applications with the Java interpreter. The basic command is:

java -jar jar-file
The -jar flag tells the interpreter that the application is packaged in the JAR file format.

The -jar option is not available for interpreters prior to version 1.2 of the Java Development Kit.

Before this command will work, however, the runtime environment needs to know which class within the JAR file is the application's entry point.

To indicate which class is the application's entry point, you must add a Main-Class header to the JAR file's manifest. The header takes the form:

Main-Class: classname
The header's value, classname, is the name of the class that's the application's entry point.

To create a JAR file having a manifest with the appropriate Main-Class header, you can use the Jar tool's m flag as described in the Modifying a Manifest section. You would first prepare a text file consisting of single line with the Main-Class header and value. For example, if your application was the single-class HelloWorld application, the entry point would of course be the HelloWorld class, and your text file would have this line:

Main-Class: HelloWorld
Assuming your text file was in a file called mainClass, you could merge it into a JAR file's manifest with a command such as this:

jar cmf mainClass app.jar HelloWorld.class
With your JAR file prepared in this way, you can run the HelloWorld application from the command line:

java -jar app.jar

 


 

Understanding the Manifest

JAR files can support a wide range of functionality, including electronic signing, version control, package sealing, extensions, and others. What gives JAR files the ability to be so versatile? The answer is embodied in the JAR file's manifest.

The manifest is a special file that can contain information about the files packaged in a JAR file. By tailoring this "meta" information that the manifest contains, you enable the JAR file to be used for a variety of purposes.

Before looking at some of the ways manifests can be modified to enable special JAR-file functionality, let's take a look at the baseline default manifest.

 

 

The Default Manifest

When you create a JAR file, it automatically receives a default manifest file. There can be only one manifest file in an archive, and it always has the pathname

META-INF/MANIFEST.MF

When a JAR file is created with version 1.2 of the Java Development Kit, the default manifest file is very simple. Here are its full contents:

Manifest-Version: 1.0

This line shows that a manifest's entries take the form of "header: value" pairs. The name of a header is separated from its value by a colon. The default manifest shows that it conforms to version 1.0 of the manifest specification.

The manifest can also contain information about the other files that are packaged in the archive. Exactly what file information is recorded in the manifest will depend on what use you intend for the JAR file. The default manifest file makes no assumptions about what information it should record about other files, so its single line contains data only about itself.

The format of the default manifest file changed between versions 1.1 and 1.2 of the Java Development Kit. If you create a JAR file for the java.math package, for example, the JDK 1.1 default manifest file would look something like this:

Manifest-Version: 1.0

Name: java/math/BigDecimal.class
SHA1-Digest: TD1GZt8G11dXY2p4olSZPc5Rj64=
MD5-Digest: z6z8xPj2AW/Q9AkRSPF0cg==

Name: java/math/BigInteger.class
SHA1-Digest: oBmrvIkBnSxdNZzPh5iLyF0S+bE=
MD5-Digest: wFymhDKjNreNZ4AzDWWg1Q==

Like the JDK 1.2 manifest file, the JDK 1.1 manifest has an entry for Manifest-Version. The version number is the same, indicating that the manifest specification didn't change between versions 1.1 and 1.2 of the JDK software.

Unlike the JDK 1.2 manifest file, the JDK 1.1 manifest has entries for each file contained in the archive, including the files' pathnames and digest values. The pathnames are given as values of the Name header. Any headers that immediately follow a Name header without any intervening blank lines, pertain to the file specified by the Name header. In the manifest above, for example, the first Name header is followed by these lines:

SHA1-Digest: TD1GZt8G11dXY2p4olSZPc5Rj64=
MD5-Digest: z6z8xPj2AW/Q9AkRSPF0cg==
Because these lines follow the Name header without any intervening blank lines, you know that the digest values they specify are the digest values for the file java/math/BigDecimal.class.

Digest values are relevant only with respect to signing JAR files. In fact, that's why the digest information isn't in the JDK 1.2 default manifest -- it isn't always needed. To learn more about digests and signing, see the Signing and Authenticating JAR Files lesson.

 

 

Special-Purpose Manifest Headers

Depending on what role you want your JAR file to play, you may need to modify the default manifest. If you're interested only in the "ZIP-like" features of JAR files such as compression and archiving, you don't have to worry about the manifest file. The manifest doesn't really play a role in those situations.

Most uses of JAR files beyond simple archiving and compression require special information to be in the manifest file. Summarized below are brief descriptions of the headers that are required for some special-purpose JAR-file functions:

 

 

Applications Bundled as JAR Files - version 1.2 only

If you have an application bundled in a JAR file, you need some way to indicate which class within the JAR file is your application's entry point. (Recall that the entry point is the class having a method with signature public static void main(String[] args).)

You provide this information with the Main-Class header, which has the general form:

Main-Class: classname
The value classname is the name of the class that is your application's entry point.

 

 

Download Extensions - version 1.2 only

Download extensions are JAR files that are referenced by the manifest files of other JAR files. See the trail on the extension mechanism for information about extensions.

In a typical situation, an applet will be bundled in a JAR file whose manifest references a JAR file (or several JAR files) that will serve as an extension for the purposes of that applet. Extensions may reference each other in the same way.

Download extensions are specified in the Class-Path header field in the manifest file of an applet, application, or another extension. A Class-Path header might look like this, for example:

Class-Path: servlet.jar infobus.jar acme/beans.jar
With this header, the classes in the files servlet.jar, infobus.jar, and acme/beans.jar will serve as extensions for purposes of the applet or application. The URLs in the Class-Path header are given relative to the URL of the JAR file of the applet or application.