What is a JAR file?
The JAR file format is based on the popular ZIP file format, and is used for aggregating many files into one. Unlike ZIP files, JAR files are used not only for archiving and distribution, but also for deployment and encapsulation of libraries, components, and plug-ins, and are consumed directly by tools such as compilers and JVMs. Special files contained in the JAR, such as manifests and deployment descriptors, instruct tools how a particular JAR is to be treated.A JAR file might be used:
- For distributing and using class libraries
- As building blocks for applications and extensions
- As deployment units for components, applets, or plug-ins
- For packaging auxiliary resources associated with components
- Security. You can digitally sign the contents of a JAR file. Tools that recognize your signature can then optionally grant your software security privileges it wouldn't otherwise have, and detect if the code has been tampered with.
- Decreased download time. If an applet is bundled in a JAR file, the applet's class files and associated resources can be downloaded by a browser in a single HTTP transaction, instead of opening a new connection for each file.
- Compression. The JAR format allows you to compress your files for efficient storage.
- Transparent platform extension. The Java Extensions Framework provides a means by which you can add functionality to the Java core platform, which uses the JAR file for packaging of extensions. (Java 3D and JavaMail are examples of extensions developed by Sun.)
- Package sealing. Packages stored in JAR files can be optionally sealed to enforce version consistency and security. Sealing a package means that all classes defined in that package must be found in the same JAR file.
- Package versioning. A JAR file can hold data about the files it contains, such as vendor and version information.
- Portability. The mechanism for handling JAR files is a standard part of the Java platform's core API.
jar tool (see The
jar tool for details) compresses files by default. Uncompressed JAR files can generally be loaded more quickly than compressed JAR files, because the need to decompress the files during loading is eliminated, but download time over a network may be longer for uncompressed files.
Most JAR files contain a META-INF directory, which is used to store package and extension configuration data, such as security and versioning information. The following files or directories in the META-INF directory are recognized and interpreted by the Java 2 platform for configuring applications, extensions, and class loaders:
- MANIFEST.MF. The manifest file defines the extension- and package-related data.
- INDEX.LIST. This file is generated by the new
-ioption of the
jartool and contains location information for packages defined in an application or extension. It is part of the JarIndex implementation and used by class loaders to speed up the class loading process.
- xxx.SF. This is the signature file for the JAR file. The placeholder xxx identifies the signer.
- xxx.DSA. The signature block file associated with the signature file stores the public signature used to sign the JAR file.
To perform basic tasks with JAR files, you use the Java Archive Tool (
jar tool) provided as part of the Java Development Kit. You invoke the
jar tool with the
jar command. Table 1 shows some common applications:
Table 1. Common usages of the
|Creating a JAR file from individual files||jar cf jar-file input-file...|
|Creating a JAR file from a directory||jar cf jar-file dir-name|
|Creating an uncompressed JAR file||jar cf0 jar-file dir-name|
|Updating a JAR file||jar uf jar-file input-file...|
|Viewing the contents of a JAR file||jar tf jar-file|
|Extracting the contents of a JAR file||jar xf jar-file|
|Extracting specific files from a JAR file||jar xf jar-file archived-file...|
|Running an application packaged as an executable JAR file||java -jar app.jar|
An executable jar file is a self-contained Java application stored in a specially configured JAR file, which can be executed directly by the JVM without having to first extract the files or set up a class path. To run an application stored in a non-executable JAR, you have to add it to your class path and invoke the application's main class by name. But by using executable JAR files, we can run an application without extracting it or needing to know the main entry point. Executable JARs facilitate easy distribution and execution of Java applications.
Creating an executable JAR is easy. You begin by placing all your application code in a single directory. Let's say the main class in your application is
com.mycompany.myapp.Sample. You want to create a JAR file that contains the application code and identifies the main class. To do this, create a file called
manifest somewhere (not in your application directory), and add the following line to it:
An executable JAR must reference all the other dependent JARs it requires through the
Class-Path header of the manifest file. The environment variable CLASSPATH and any class path specified on the command line is ignored by the JVM if the
-jar option is used.
Now that we've packaged our application into an executable JAR called ExecutableJar.jar, we can launch the application directly from the file using the following command:
java -jar ExecutableJar.jar
To seal a package, add a
Name header for the package, followed by a
Sealed header with value "true" to the JAR manifest file. Just as with executable JARs, you can seal a JAR by specifying a manifest file with the appropriate header elements when the JAR is created, as shown here:
Nameheader identifies the package's relative pathname. It ends with a "/" to distinguish it from a filename. Any headers following a
Nameheader, without any intervening blank lines, apply to the file or package specified in the
Nameheader. In the example above, because the
Sealedheader occurs after the
Nameheader without intervening blank lines, the
Sealedheader will be interpreted as applying only to the package
If you try to load a class in a sealed package from another source other than the JAR file in which the sealed package lives, the JVM will throw a
Extensions add functionality to the Java platform, and an extensions mechanism is built into the JAR file format. The Extensions mechanism allows JAR files to specify other required JAR files via the
Class-Path headers in the manifest file.
The JVM effectively automatically adds JARs referenced in a
Class-Path header to the class path when loading a JAR that uses the extension mechanism. However, the extension JAR path is interpreted as a relative path, so in general the extension JAR must be stored in the same directory as the JAR referencing it.
For example, assume the class
ExtensionClient, which references class
ExtensionDemo, is bundled in a JAR file called ExtensionClient.jar, and that the class
ExtensionDemo is bundled in ExtensionDemo.jar. In order for ExtensionDemo.jar to be treated as an extension, ExtensionDemo.jar must be listed in the
Class-Path header in ExtensionClient.jar's manifest, as follows:
Class-Pathheader in this manifest is ExtensionDemo.jar with no path specified, indicating that ExtensionDemo.jar is located in the same directory as the ExtensionClient JAR file.
jarsignertool or directly through the
java.securityAPI. A signed JAR file is exactly the same as the original JAR file, except that its manifest is updated, and two additional files are added to the META-INF directory, a signature file and a signature block file.
A JAR file is signed using a certificate stored in the Keystore database. Certificates stored in the keystore are protected with a password, which must be provided to the
jarsigner tool to sign a JAR file.
Each signer of a JAR is represented by a signature file with the extension .SF within the META-INF directory of the JAR file. The format of the file is similar to the manifest file -- a set of RFC-822 headers. As shown below, it consists of a main section, which includes information supplied by the signer but not specific to any particular JAR file entry, followed by a list of individual entries which also must be present in the manifest file. To validate a file from a signed JAR, a digest value in the signature file is compared against a digest calculated against the corresponding entry in the JAR file.Listing 1. Manifest and signature files in signed JARs
A digital signature is a signed version of the
.SF signature file. Digital signature files are binary files and have the same filename as the
.SF file but a different extension. The extension varies depending on the type of digital signature -- RSA, DSA, or PGP -- and on the type of certificate used to sign the JAR.
keystores. The JDK contains tools for creating and modifying keystores. Each key in the keystore can be identified by an alias, which is typically the name of the signer who owns the key.
All keystore entries (key and trusted certificate entries) are accessed with unique aliases. An alias is specified when you add an entity to the keystore using the
keytool -genkey command to generate a key pair (public and private key). Subsequent
keytool commands must use this same alias to refer to the entity.
For example, to generate a new public/private key pair with the alias "james" and wrap the public key into a self-signed certificate, you would use with the following command:
keytool -genkey -alias james -keypass jamespass
keytoolwill automatically create it.
jarsignertool uses keystore to generate or verify digital signatures for JAR files.
Assuming you've created the keystore "jamesKeyStore" as in the example above, and it contains a key with alias "james," you can sign a JAR file with the following command:
jarsigner -keystore jamesKeyStore -storepass jamesKeyStorePass
jarsigner tool can also verify a signed JAR file; this operation is considerably simpler than signing the JAR file. Just execute the following command:
jarsigner -verify SSample.jar
jarsignertool will tell you the JAR has been verified; otherwise, it will throw a
SecurityExceptionindicating which files could not be verified.
JARs can also be signed programmatically using the
java.security APIs. Alternatively, you can use tools such as Netscape Object Signing Tool.
You can also sign JARs programmatically using the
java.security APIs. (See Resources for details). Alternatively, you can use tools such as the Netscape Object Signing Tool.
If an application or applet is bundled into multiple JAR files, the class loader uses a simple linear search algorithm to search each element of the class path, which may entail the class loader downloading and opening many JAR files until the class or resource is found. If the class loader tries to find a nonexistent resource, all the JAR files within the application or applet will have to be downloaded. For large network applications and applets this could result in slow start up, sluggish response, and wasted network bandwidth.
Since JDK 1.3, the JAR file format has supported indexing to optimize the process of searching for classes in network applications, especially applets. The JarIndex mechanism collects the contents of all the JAR files defined in an applet or application and stores the information in an index file in the first JAR file. After the first JAR file is downloaded, the applet class loader will use the collected content information for efficient downloading of JAR files. This directory information is stored in a simple text file named INDEX.LIST in the META-INF directory of the root JAR file.
-ioption to the
jarcommand. Suppose we have a directory structure as depicted in the following diagram:
Figure 2. JarIndex
You would use the following command to create an index file for JarIndex_Main.jar, JarIndex_test.jar, and JarIndex_test1.jar:
jar -i JarIndex_Main.jar JarIndex_test.jar SampleDir/JarIndex_test1.jar
Listing 2. Example JarIndex INDEX.LIST file
The JAR format is much more than an archive format; it has many features for improving the efficiency, security, and organization of Java applications. Because these features are built into the core platform, including the compiler and classloader, developers can leverage the power of the JAR file format to simplify and improve their development and deployment processes.