by Alan Liu
JAR files are a new feature introduced in JDK 1.1. The name JAR stands for Java ARchive and also deliberately resembles the name of the tar UNIX archiving format. The similarity between JAR and tar files ends there, however. While tar files are simple, uncompressed file archives, JAR files provide compression, backward compatibility to existing Java applets, portability, and security features. JAR files will soon become the standard, preferred way to distribute Java applets.
The JAR file format brings several important advantages to applets. These include performance improvements and enhanced portability. JAR files also implement the JDK 1.1 Security Model, described in detail in Chapter 36, "Java Security in Depth."
JAR archives are not the first Java archive format to be supported. Since version 1.0, the JDK has used the uncompressed ZIP file classes.zip to store the JDK system class files as a single disk file. Netscape Navigator 3.0, following this procedure, allows the APPLET tag to load an applet from a similar ZIP file. Microsoft Internet Explorer 3.0 can load ActiveX controls from Microsoft's CAB files.
JAR files will probably replace these other mechanisms over time. They offer the following benefits which make them the preferred choice.
A complex applet may consist of dozens or hundreds of Java classes, each stored in a separate class file (recall that each public class must be stored in a separate file). To run the applet, the Web browser makes an HTTP connection to load each file, as needed, from the server. Establishing an HTTP connection entails overhead, and if the class files are small, as they typically are, much of the time spent loading an applet can be spent establishing the multiple HTTP connections required to load all the class files.
The first and most obvious benefit of a JAR file is that it combines several class files into one archive file, which can then be transmitted from the server to the Web browser over a single HTTP connection. Furthermore, JAR files can contain not only class files but also audio and image files, allowing an entire applet to be downloaded in one transaction. This is useful not only for improved performance, but also because it simplifies applet distribution.
JAR files, like CAB files (but unlike classes.zip and the ZIP files used Netscape Navigator 3.0), are compressed using a variant of the standard Lempel-Ziv algorithm. For example, the JDK 1.1 TicTacToe demo is 20 percent smaller when archived as a JAR file, while the ImageMap demo is 5 percent smaller (it contains more image files, which are already compressed). By not only aggregating multiple files but also compressing them, JAR files can greatly reduce the time needed to download an applet.
Because JAR archives preserve the directory hierarchy of their files, and because they can be loaded through a simple change to the APPLET tag, JAR archives can be used transparently with existing Java applets, with no change to the applet code.
Portability, in this case, refers to two things: portability between browsers, and portability between Web servers.
Browser incompatibility between Netscape Navigator, Microsoft Internet Explorer, and other browsers is a familiar bugaboo to anyone who has developed Web pages or Java applets. In terms of applet archives, this incompatibility is worse than ever: Navigator supports uncompressed ZIP files, but Internet Explorer doesn't support anything (CAB files are for ActiveX controls, not Java applets). Prior to JDK 1.1, a Web developer had no portable archiving mechanism.
JAR files solve this problem by providing a single, browser-independent archive file format. Since JAR support and tools are implemented entirely in Java, any browser supporting the standard JDK 1.1 library will be able to support JAR files.
The other side of the portability question becomes clear when you try to move an applet from one Web server to another. For example, imagine that you have developed an applet running on a Windows 95-based Web server. Your files have descriptive names such as NavigationBarAnimationPanel.class--a legal file name under Windows 95. Now you need to move your Web site to a Macintosh-based Web server. Unfortunately, you discover that Macintosh file names are limited to 31 characters, and you are forced to rename not only your Java source files, but also your classes within them (since file names must match the names of classes they contain).
(To see this firsthand, try downloading and installing the JDK 1.1 beta 2 documentation files on a Macintosh. Many of the file names will be truncated, and your browser won't be able to navigate links to those files.)
By storing an applet's various class files and other resource files in a single JAR file, you make the applet immune to any idiosyncrasies of the Web server's underlying file system.
As of JDK 1.1, the Java Security Model has been extended. It is now possible, by using authenticated JAR archives, for the user to verify the origin of an applet, mark it as trusted, and give it additional privileges. This makes it possible for new types of applets to be written, such as word processors that store files on the local user's hard disk.
You should consider using a JAR archive for your applet if any of the following apply:
TIP: JAR files are useful chiefly for applets. If you are developing a Java application, JAR files won't be as useful to you, although you may still use them as a general-purpose archiving format.
In order to use JAR archives, you need to know how to create them using the jar tool, and you need to know how to load them using the APPLET tag.
TIP: There is nothing different about the way an applet in a JAR archive is written.
The only requirement here is that the applet's files should all be located in a single
directory, or in subdirectories of that directory. For example, you may have a directory
containing all your class files, and two subdirectories named images and
audio, which contain JPEG and AU files.
From within the applet's main directory, use the command:
jar cvf jar_file_name input_file_1 input_file_2 É
Example:
jar cvf Blinker.jar *.class images audio
Add the ARCHIVES field to your APPLET tag as follows:
<APPLET CODE=applet_name ARCHIVES=archive_name>...</APPLET>
Example:
<APPLET CODE=Blinker.class ARCHIVES=Blinker.jar>...</APPLET>
In most cases, this means a browser that implements JDK 1.1 or later.
NOTE: At the time of this writing, only HotJava 1.0 preBeta2 and the appletviewer tool of JDK 1.1 support JAR files. Netscape Navigator 4.0 will probably support JAR files in its final release. Microsoft has not yet committed to supporting all of JDK 1.1, so it's unknown whether Internet Explorer 4.0 will support JAR files or not.
The jar tool allows you to create, list, and extract files from JAR archives.
It deliberately resembles the UNIX tar tool, both in function and in usage.
Like other tools in the JDK, the jar tool is implemented as a Java application,
making it portable to any platform supporting Java.
Creating a New Archive
jar cvf Foo.jar *.class images
will create a new JAR archive named Foo.jar in the current directory. The archive will contain all the class files in the current directory, as well as the complete images directory and all its contents.
As an example, connect to the directory containing the JDK 1.1 demo TicTacToe.
NOTE: A better example might be the ImageMap demo, but because of a bug in the JDK 1.1 beta 2 appletviewer tool, use the TicTacToe demo. See "Compatible Browsers" later in this chapter.
D:\java\demo\TicTacToe>dir Volume in drive D is NTFS20 Volume Serial Number is 6C98-56B4 Directory of D:\jdk1lb2\java\demo\TicTacToe 01/13/97 10:04a <DIR> . 01/13/97 10:04a <DIR> .. 12/16/96 11:29a <DIR> audio 11/19/96 12:34p 139 example1.html 12/16/96 11:29a <DIR> images 11/19/96 12:34p 3,454 TicTacToe.class 12/06/96 10:27a 7,593 TicTacToe.java 7 File(s) 11,186 bytes 1,575,772,160 bytes free
Create a new subdirectory that will contain the JAR file version of this applet.
D:\java\demo\TicTacToe>mkdir jar
Now create the JAR archive.
D:\java\demo\TicTacToe>jar cvf jar\TicTacToe.jar *.class audio images adding: TicTacToe.class adding: audio/beep.au adding: audio/ding.au adding: audio/return.au adding: audio/yahoo1.au adding: audio/yahoo2.au adding: images/cross.gif adding: images/not.gif
Notice that when directories are listed as input files to the jar tool, their contents are added to the archive and the directory names are preserved.
When the jar tool creates a new archive, it automatically adds a manifest
file to the archive. In most cases, this will suffice. However, should you wish to
create your own manifest file, and have the jar tool use that, you can do
so by specifying the m option.
Listing Archive Contents
jar tvf Foo.jar
will list the contents of Foo.jar.
To continue with the TicTacToe demo applet, connect to the jar subdirectory you created previously. Use the t option to obtain a listing.
D:\java\demo\TicTacToe\jar>jar tf TicTacToe.jar META-INF/MANIFEST.MF TicTacToe.class audio/beep.au audio/ding.au audio/return.au audio/yahoo1.au audio/yahoo2.au images/cross.gif images/not.gif
Notice that a manifest file has been added to the archive automatically. See the section "Manifest File," later in this chapter, for more information about manifest files. You can obtain more information by using the v option.
D:\java\demo\TicTacToe\jar>jar tvf TicTacToe.jar 1045 Mon Jan 13 11:52:18 PST 1997 META-INF/MANIFEST.MF 3454 Tue Nov 19 12:34:26 PST 1996 TicTacToe.class 4032 Tue Nov 19 12:34:26 PST 1996 audio/beep.au 2566 Tue Nov 19 12:34:26 PST 1996 audio/ding.au 6558 Tue Nov 19 12:34:26 PST 1996 audio/return.au 7834 Tue Nov 19 12:34:26 PST 1996 audio/yahoo1.au 7463 Tue Nov 19 12:34:26 PST 1996 audio/yahoo2.au 157 Tue Nov 19 12:34:24 PST 1996 images/cross.gif 158 Tue Nov 19 12:34:24 PST 1996 images/not.gif
Extracting Files from an Archive
D:\java\demo\TicTacToe\jar>jar xvf TicTacToe.jar TicTacToe.class extracted: TicTacToe.class, 3454 bytes
If you are following along on your computer, remove the file you just extracted so that upcoming examples will work.
D:\java\demo\TicTacToe\jar>del TicTacToe.class
TIP: You cannot use the x option to extract a single file within a subdirectory of the JAR archive. Instead, specify the entire subdirectory and, after it has been extracted, discard those files that you do not need.
The APPLET tag embeds a Java applet into an HTML file. It has a number of attributes that specify the name of the applet to be loaded, the URL to use to locate the applet, and the size of the applet on the page. In addition to these attributes, any number of parameters can be specified. For example,
<APPLET CODE="FooMain.class" WIDTH=100 HEIGHT=120> <PARAM NAME="color" VALUE="red"> <PARAM NAME="background" VALUE="blue"> </APPLET>
The CODEBASE attribute indicates the URL base from which to load the class file. If no CODEBASE is specified, then the URL of the referring page is used. For example, the browser will try to load the following applet from http://www.foo.com/applets/FooMain.class:
<APPLET CODE="FooMain.class" CODEBASE="http://www.foo.com/applets/" WIDTH=100 HEIGHT=120> ... </APPLET>
Beginning with JDK 1.1, Sun has specified changes to the APPLET tag which allow the class to be loaded from a JAR archive, that is downloaded before the Java applet class is located.
Loading from a JAR archive can be specified in two ways: using an attribute or using a parameter. First, an attribute named ARCHIVES can be used. For example:
<APPLET ARCHIVES="Foo.jar" CODE="FooMain.class"> ... </APPLET>
When the browser reads this tag, it first downloads the Foo.jar file from the server, then tries to find the FooMain.class in Foo.jar. If the browser cannot find the class in the archive, it looks at the location specified by the CODEBASE, as usual.
Alternatively, the JAR archive can be specified as a parameter. This parameter should have the name ARCHIVES. The parameter's value is the name of the JAR file. For example:
<APPLET CODE="FooMain.class"> <PARAM NAME=ARCHIVES VALUE="Foo.jar"> ... </APPLET>
It's possible to specify more than one JAR archive to be loaded. To do so, insert the string " + " (a plus sign surrounded by spaces) between the archive file names, as follows:
<APPLET ARCHIVES="foo.jar + foo_images.jar + foo_sounds.jar" CODE="FooMain.class"> ... </APPLET>
Specifying a JAR archive in an APPLET tag is a performance optimization, instructing the browser to preload a specified archive and use that archive, if possible, when locating classes. If the JAR file is not found, or if a required class file is not found in the archive, then the usual search procedure, as defined by JDK 1.0, will be followed. Specifying a JAR file to preload does not prevent the usual search paths from being tried and used if necessary.
CAUTION:
If you have been using the Netscape Navigator APPLET tag, which allows loading of an applet from an uncompressed ZIP file, you should be aware of a subtle change in Sun's APPLET tag definition: Netscape's APPLET tag uses an ARCHIVE attribute, while the tag described here uses an ARCHIVES attribute--notice the different spelling.
<title>TicTacToe</title> <hr> <applet code=TicTacToe.class width=120 height=120> </applet> <hr> <a href="TicTacToe.java">The source.</a>
Copy this to the subdirectory jar that you created previously.
D:\java\demo\TicTacToe>copy example1.html jar 1 file(s) copied.
Now edit it to add the APPLETS attribute. It should look like Listing 35.2 when you're done.
<title>TicTacToe</title> <hr> <applet code=TicTacToe.class archives=TicTacToe.jar width=120 height=120> </applet> <hr> <a href="TicTacToe.java">The source.</a>
Now you should be able to run the TicTacToe applet from the JAR archive created earlier.
D:\java\demo\TicTacToe\jar>appletviewer example1.html loading d:\jdk1lb2\java\bin\..\lib\awt.properties
By the time you are reading this, versions of Netscape Navigator or Microsoft Internet Explorer may be available that support JDK 1.1 and the JAR file format. However, if you are using Navigator 3.0 or Internet Explorer 3.0, you will find that they will not load JAR files. The reason is simple: These versions use JDK 1.0, not 1.1.
At the time of this writing, Sun has released version 1.0 preBeta2 of its HotJava browser which supports JDK 1.1 and JAR files. You can also use the appletviewer tool of JDK version 1.1 or later to test the loading of JAR files. Specify an APPLET tag, as described previously, in an HTML file, and then load that HTML file with appletviewer.
The Web allows content to be downloaded. The Java architecture allows executable content to be downloaded. While this opens up tremendous new possibilities, it also opens up new risks. While a static text or image file can do little to harm its receiver (Snow Crash notwithstanding), a piece of code can, potentially, do a lot of damage--witness computer viruses.
In order to protect recipients of downloaded code, Java implements a security model known as the "sandbox." This is a domain within which an untrusted piece of Java code may do whatever it wishes. By restricting the applet's activities to a well-defined area, a browser can run an untrusted applet while still protecting everything outside the sandbox--typically, the local machine's memory, files, and disks, and the network.
Running within the sandbox is not a hindrance to an applet that displays a clock, a stock ticker, or an animated navigation bar. But what about an applet that implements a word processor or a spreadsheet? For such an applet to be useful, it needs to interact with the user's local machine in order to read and write files (unless the applet wants to tackle the formidable task of maintaining user data files on a remote server). To do this, it needs to leave the sandbox. Under JDK 1.0, it was difficult for applets to do this. Under JDK 1.1, using authenticated JAR archives, applets have a standard way to easily gain trusted status.
The first entry in any JAR file is a collection of meta-information about the archive. The jar tool generates this meta-information automatically and stores it in a top-level directory named META-INF. This directory always contains what is known as the manifest file, META-INF/MANIFEST.INF (see Listing 35.3).
Normally, if no authentication is applied, the manifest file contains checksums for the other files in the archive. For example, you can extract the manifest file for the TicTacToe.jar archive, created previously, as follows:
D:\java\demo\TicTacToe\jar>jar xvf TicTacToe.jar META-INF extracted: META-INF/MANIFEST.MF, 1045 bytes
Manifest-Version: 1.0 Name: TicTacToe.class Hash-Algorithms: MD5 SHA MD5-Hash: TsjcL1vWU7k4/HDkwOnvHg== SHA-Hash: IGRKfYKD8Cpef7+or5ZKqYp3bh0= Name: audio\beep.au Hash-Algorithms: MD5 SHA MD5-Hash: kZv279ZIA/H6mOw4t8W8XA== SHA-Hash: JgfdUl4/uzNq5yUy3e07ZXwvNOc= Name: audio\ding.au Hash-Algorithms: MD5 SHA MD5-Hash: 23oJDEp/LqCZC70AEIOsVQ== SHA-Hash: dpRUB8DKzEP0Grc7DIrXclPMjJ8= Name: audio\return.au Hash-Algorithms: MD5 SHA MD5-Hash: tBUwkF2qeyor/nmPeF81hg== SHA-Hash: ABV7Ar1gRYQmpp7kSbkH3GN+YOA= Name: audio\yahoo1.au Hash-Algorithms: MD5 SHA MD5-Hash: Bq9PhKz6zAWrgQvtGWS8zQ== SHA-Hash: qUO3jWxRvJWIp25S9XRQk5lbLaY= Name: audio\yahoo2.au Hash-Algorithms: MD5 SHA MD5-Hash: 6lhsclKkFy5iBu+km+DAVQ== SHA-Hash: Gfc7hOmtTmM31JJlHJZgkMm2elo= Name: images\cross.gif Hash-Algorithms: MD5 SHA MD5-Hash: gTJaDGQtdz1Y4W+hHWxjgA== SHA-Hash: plA3I8zoS3u8XXj9+vutZupQo0U= Name: images\not.gif Hash-Algorithms: MD5 SHA MD5-Hash: SJspO4DooHqq9ndFnn6S6w== SHA-Hash: MmqEk9R8pMigNK3xDi2yK1cyyZ8=
The manifest file lists all the files in the archive, together with values labeled MD5-Hash and SHA-Hash. Listing 35.3 shows a typical manifest file. MD5 and SHA are message digests, also known as one-way hash functions. A hash function takes an arbitrary piece of input data and produces a piece of output data of a fixed size. MD5 hashes are 128 bits; SHA hashes are 160 bits. The term "one-way" refers to the fact that it is difficult to produce the same hash from two different inputs.
The message digests in this manifest can be used to confirm that the archive has not undergone accidental corruption: As a browser reads each file from the archive, it can compute its MD5 and SHA hash values and check them against those in the file. Deliberate corruption, on the other hand, cannot be ruled out, since anyone who intentionally corrupts an archive file can also modify the manifest file's corresponding hash.
It is possible, however, to detect deliberate corruption of the files in a JAR archive. To do so, the JAR archive must be "signed." This is analogous to signing a paper document with a pen. It indicates, with certainty, that the given JAR archive came from the indicated source. In fact, a digital signature is stronger than a physical one; it is harder to forge, it cannot be repudiated by the signer, and the signed document cannot be modified.
In order to sign a JAR archive, you must first create a private key, a public key, and a certificate. The public and private keys are paired pieces of data used to create digital signatures and to encrypt data. A certificate is a guarantee by one entity, usually a trusted public organization, that another entity's public key is valid. (In this case, more specifically, a certificate conforms to the X.509 standard published by CCITT.) The combination of a public key and a certificate can be used to confidently verify a digital signature.
The javakey tool handles the creation and management of identities, public and private keys, and certificates. The details of key and certificate creation and management are beyond the scope of this chapter, but they are covered in Chapter 36, "Java Security in Depth."
Once you have a public key, a private key, and a certificate, you need one more
thing to sign an archive. This is the directive file, which specifies the
signer, certificate, and the name to be used for the signature file. The directive
file consists of fields of name-value pairs. The required fields are given in Table
35.1. For an example directive file, see Listing 35.4.
Field Name | Field Value |
signer | Name of the signer. This name must already be registered in the persistent database maintained by javakey. |
cert | Certificate number to use for the given signer. The first certificate is number 1. |
chain | Chain depth for a chain of certificates. This is currently not supported; use 0. |
signature.file | A name, 8 characters or shorter, to assign the signature and certif-icate files that will be created in the META-INF directory of the signed JAR archive. |
signer=liu cert=1 chain=0 signature.file=LIUSIGN
To sign a JAR file, use the javakey tool with option -gs and two arguments: the name of the directive file, and the name of the JAR archive file. For example, the following command signs the archive Foo.jar using the directive file LiuJDF.txt:
javakey -gs LiuJDF.txt Foo.jar
In response to this command, javakey would create two entries in the META-INF directory of the archive; the signature file LIUSIGN.SF and the certificate file LIUSIGN.DSA.
NOTE: Although a purported feature of JAR archives is the ability to sign individual files, the current release of the javakey tool does not seem to support this.
New to JDK 1.1 is the package java.util.zip, which contains a number of classes that manipulate JAR archive files. Although you will typically not need to use these classes, it is helpful to understand them at a general level. You do not need to use these classes to create or load JAR files; you can use the jar tool and the JDK 1.1 APPLET tag for that.
The java.util.zip package defines the Checksum interface. The Checksum interface defines a protocol for a class that computes the checksum of a stream. java.util.zip provides two classes that implement the Checksum interface: Adler32 and CRC32.
The package java.util.zip defines of the following fourteen classes.
ZipFile
ZipEntry
Adler32 and CRC32
CheckedInputStream and CheckedOutputStream
Deflater and Inflater
DeflaterOutputStream and InflaterInputStream
GZIPOutputStream and GZIPInputStream
ZipOutputStream and ZipInputStream Typically, you will not use the classes in java.util.zip to read a JAR
file; you will specify the archive to be read in your APPLET tag, and the browser
will do the rest. However, should you need to read a JAR file yourself, this section
will get you started. First, enter the following file (Listing 35.5), named DumpJAR.java.
Now compile it: If you run this application on the TicTacToe.jar file created earlier,
you will see a listing of its contents. Notice that the entries are not shown in
the same order that the jar tool produces. You should not depend on the
order of entries returned by the ZipFile.entries() method. The JAR file format is based on the general-purpose, freely usable ZLIB file format.
This is a portable file format designed to store multiple files in a directory hierarchy.
The ZLIB format is not specific to any single compression method; however, the deflate
compression scheme is commonly used. This is the compression method used in JAR files.
The deflate protocol is based on a variant of the Lempel-Ziv algorithm,
LZ77, and features low compression overhead and well-defined runtime memory requirements.
This makes it a good general-purpose compression protocol. For more information about
ZLIB, refer to RFC 1950 and RFC 1951, available at ftp://ds.internic.net/rfc/. In general, you won't need to concern yourself with the details of the JAR file
format, since you'll interact with JAR files through the jar and javakey
tools and possibly the java.util.zip package.
Reading a JAR File Programmatically
Listing 35.5
import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;
import java.util.Enumeration;
class DumpJAR
{
public static void main(String[] args)
{
String file_name = args[0];
try
{
ZipFile zip = new ZipFile(file_name);
PrintEntryNames(zip);
}
catch (java.io.IOException e)
{
System.out.println("Exception " + e);
}
}
public static void PrintEntryNames(ZipFile zip)
{
for (Enumeration e = zip.entries(); e.hasMoreElements(); )
{
ZipEntry entry = (ZipEntry)e.nextElement();
System.out.println(entry.getName());
}
}
}
D:\java\demo\TicTacToe\jar>javac DumpJAR.java
D:\java\demo\TicTacToe\jar>java DumpJAR TicTacToe.jar
audio/return.au
audio/ding.au
TicTacToe.class
audio/yahoo1.au
audio/yahoo2.au
images/not.gif
audio/beep.au
images/cross.gif
META-INF/MANIFEST.MF
JAR File Format