Java classes forming an application, Applet, or weblet can be bundled up
into something that looks very much like a ZIP file. JavaBeans are also packaged
in JAR files. In JDK 1.1+ compression is turned on by default and in earlier
versions it was always off. It is faster to download a group of classes as a
single JAR file since HTTP has high overhead to set up a connection for each
file transferred. The tools Jar.exe and jarsigner.exe
come bundled with the JDK.
Jar vs Zip
A JAR file differs from a standard ZIP in that:
-
It includes a manifest member: meta-inf/Manifest.mf,
that describes the JAR's contents and provides checksums. The manifest is just a
zip member you can read in the ordinary way, or access with
java.util.jar.Manifest : available:
-
Jar files always use / as the separator between directory names, never \,
however Winzip will display them as \. You can
check what they really are / with a hex viewer such as SlickEdit.
Directory names must precisely match package names, case sensitive.
-
In JDK 1.0.2 the files inside a jar were not compressed. In JDK 1.1+ they
usually are. Jars don't support all the PKZip
compression formats.
-
The directory includes long filenames, not just 8+3.
-
Jars may optionally be signed. For Netscape-style signing you will see two extra
files:
-
zigbert.rsa which contains your public jar-signing key
and a stripped down version of your jar-signing certificate.
It contains your public key, your company name, your certificate expiry date,
your signing authority's public key, your signing authority's name, and your
signing authority's expiry date. Your private key is not present. Your
certificate is digitally signed with the signing authority's private key. By
that I mean, the checksum of your certificate is encrypted with the signing
authority's private key. It can be decrypted with the signing authority's public
key to verify the signature. The browser's public key is pre-installed in the
browser for verification.
-
zigbert.sf which looks much like a manifest file. It
contains the digital signatures of each member of the jar file. These are
encrypted with your certificate's private key. They can be decrypted for
verification with your certificate's public key. Netscape computes them a
slightly different way from Sun.
Sun's jarsigner and Netscape 4.79's signtool
1.1, 1.2 and 1.3 produce different information and layout in the JAR archives.
For details of how this information is used to verify a signed jar, see certificate.
If the jar is digitally signed there is the possibility of Applets escaping the
restrictions of the sandbox. You don't need to sign your jar files if your
Applets are willing to live with the usual security restrictions. Since Netscape,
Microsoft and Sun use incompatible signing techniques, you may have to sign your
jar file multiple times or have separate jars for each of the bewildering array
of signing and security schemes. To make matters worse, Internet Explorer
ignores signing in jar files. It only pays attention to it in cab files. When
the elephants fight, it is the grass that suffers. See signed
Applets for more information.
-
For Sun signed jars there are two extra files phony.dsa
(a binary representation of your public key and of your signing certificate),
and phony.sf which looks like a duplicate of the
manifest except the hashes values are different. Name phony matches your
cert alias, so you might like to pick one that looks better to the public. Why
are both the manifest hashes and the phony.sf hashes
needed? I suspect the manifest hashes are simple hashes and that the phony.sf
hashes are actually encryptions of those hashes.
-
Starting with JDK 1.2, a jar may be executable by designating one class in it as
the official class to start when the jar as a whole is executed. The key is an
attribute line in the manifest file of the form:
Main-Class: com.mindprod.mypackage.MyClass
See Main-Class for details. If you then associate *.jar
files with java.exe you can just write myJar.jar on
the commmand line and it will automatically start the program.
-
JDK 1.2+ has many new classes for handling jars. java.net.JarURLConnection
lets you access a remote jar just as if it were a remote sequential file by
using a new URL syntax: jar:http://www.foo.com/bar/baz.jar!/COM/foo/Quux.class.
The !/ separates the member name from the filename. java.util.jar.JarFile
lets you randomly process local jar files. java.net.URLClassLoader
lets you load classes from arbitrary jar sources, not just the archive jars.
Tips on Using Jar Files
-
The directory path names stored inside the Jar should
exactly match the package names, no extra qualification. There must be no
drive letters. jar.exe won't warn you if you
screw up! They must match in case precisely as well. Check with winzip
that you have not inadvertently included C:\ in
your directory/package names. Whatever you put on the command line goes in raw
as the path. You must thus juggle your current directory before using jar.exe
to make things work out.
-
You can put a data file inside the Jar file (a resource) and access it with code
like this:
InputStream fis = MyApp.class.getResourceAsStream( "InWords.properties" );
where InWords.properties is the name of the file
inside the jar file you want to read. Class.getResource
makes these changes to the resource name: if the resource name starts with "/",
it is unchanged; otherwise, the package name is prepended to the resource name
after converting "." to "/". This allows you to use either
dots or slashes to separate the components of the name.
Class.getResource is broken, in that Netscape 4.0.x
does not support it. See Netscape's apology.
Now that Netscape 7.02 is available, perhaps we can ignore that restriction.
To get information out of jar files other than the main jar, you would need to
use ZipFile and ZipEntry.getInputStream.
To see how to fish GIFs and JPGs out of jar files, see Image.
-
Names of resources and their paths are case sensitive in
a jar. You may have been lulled into a false sense of security because, under
Windows, resources outside the jar are case-insensitive. When you pack your
application into a jar, it stops working.
-
See the java.util.zip.ZipOutputStream class to write
jar files. Normally you manipulate them with jar.exe
or Winzip.
-
Microsoft Internet Explorer does not support digitally signed jar files. It uses
Microsoft-proprietary single-platform cab files instead. However, recent
versions can deal with unsigned jar files. With the Java Plug-in it can also
deal with Sun-style signed jars.
-
If you use the -jar option, java.exe
ignores the classpath. It will only look in that jar.
-
Beginning with JDK 1.2.2 it is no longer possible to use a Jar file in which
some classes of a package are signed and others are unsigned or signed by a
different signer. See signed Applets.
Building Jar Files
You can create or read jar files with the java.util.zip classes, or with Sun's Jar.exe.
utility.
Sun's Jar Reference : available:
You can download the JDK
documentation pack. Visual Cafe has an excellent jar builder. You can also use Winzip
version 6.3 or later to view or delete files. Unfortunately Winzip
there are several problems in using Winzip to
create jar files or to add files to them. I have written the Winzip
people several times asking for some simple extensions to make Winzip
suitable for dealing with jar files, but each time they have refused.
If you are using packages, for jar.exe you must
be in the root directory when using jar.exe to
ensure your package names get properly included because the names you give jar.exe
on the command line are the names it will blindly use for your packages inside
the created jar file. You don't want any names like C:\com\mindprod\mypackage.MyClass.class
or \com\mindprod\mypackage.MyClass.class or MyClass.class
(unless you have no packages). You want names like com\mindprod\mypackage\MyClass.class
which translates to com.mindprod.mypackage.MyClass.class
on the command line. They have to make sense both as filenames and as fully
qualified package/class names.
If you are not using packages, you must be in the directory where the
class files are when you build your jar. That way the filename MyClass.class
will be the same as the classname MyClass.class.
Here is some typical code to build a jar file.
See Main-Class for details on how to create the main.mft
file. See jar.exe for another explanation of how to
use it.
Executing Jar Files
For JDK 1.4+, after you have built the Main-Class entry,
and set up an association of the *.jar extension to C:\Program Files\Java\j2re1.4.2_04\bin\java.exe,
all you need to do to run the jar is:
converter.jar
or
java.exe -jar converter.jar
For JDK 1.1, you need a little more, something like this:
java.exe -classpath converter.jar;D:\vcp\JAVA\LIB\CLASSES.ZIP com.mindprod.Converter.Converter
To run the jar in an Applet, see Applet for some sample HTML or see Sun's
basic documentation on doing it.
Making Jar Files Double Clickable
In Windows 95/98/ME/NT/2000 you can set up the extension *.jar
so that when you double click on a jar file in the disk explorer it will start
executing the main-class of the jar.
-
Click Start | Disk Explorer | View | Options | File Types |
Executable Jar file | edit.
-
If there is no Executable Jar file entry click
new to create one and fill in the Description of type to jar
- Java executable.
-
Change the name of the entry from Executable Jar file
to something that will sort where you expect it like jar -
Java executable.
-
Change the content type to the proper MIME type. See MIME
for details.
-
Set default extension for Content type to .jar.
-
Click open | edit .
-
If there is no open, Click new and set the action to open.
-
Set the application to perform to: "C:\program files\JavaSoft\JRE\1.4.0_01\bin\javaw.exe"
-jar "%1". You can browse or adjust as necessary to account for
where you put your javaw.exe
-
Uncheck DDE.
-
Click OK.
-
Click new and set the action to execute.
-
Set the application to perform to: "C:\program files\JavaSoft\JRE\1.4.0_01\bin\javaw.exe"
-jar "%1". You can browse or adjust as necessary to account for
where you put your javaw.exe
-
Uncheck DDE.
-
Click OK.
-
Click new and set the action to edit.
-
Set the application to perform to: "D:\program files\WinZip\winzip32.exe"
"%1". You can browse or adjust as necessary to account for
where you put your Winzip program.
-
Uncheck DDE.
-
Click OK.
-
Click execute | set default.
-
Click always show extension.
-
click change icon. Choose a nice icon. Perhaps some
friendly artist could provide me with an jar.ico file
I could share with everyone.
-
click close, close.
-
Write a letter to Microsoft asking them to automate this bubblegum. Tell them to
end the warring between apps. Allow more than one app to register per function.
The ones you use most often should bubble to the top. Tell them that whether
apps are properly installed or uninstalled, this information should be self-healing.
The Manifest
The manifest is a member file inside a JAR file describing
the contents of the JAR archive. It always has the name /META-INF/MANIFEST.MF.
For a Netscape 4.79 digitally signed Jar file, it looks like this: An unsigned
version quite simple in that it contains just three lines:
Manifest-Version: 1.0
Created-By: 1.4.0 (Sun Microsystems Inc.)
Main-Class: com.mindprod.Bio.Biorhythms
A Sun signed version is more complex in that it also contains a hash for each
member put here by jarsigner.
Manifest-Version: 1.0
Created-By: 1.4.0 (Sun Microsystems Inc.)
Main-Class: com.mindprod.Bio.Biorhythms
Name: cmp/Bio/Biorhythms.class
SHA1-Digest: ueEw1mJ4aOXT9vmosR0nM/eUt6Y=
Name: cmp/Bio/SelectableDate.class
SHA1-Digest: 8HylCo90The8D1mBuYEEOFQDUsY=
A Netscape signed version is more comlex still in that in has two different
hashes for each member put there by signtool.
Manifest-Version: 1.0
Created-By: Signtool (signtool 1.3)
Comments: PLEASE DO NOT EDIT THIS FILE. YOU WILL BREAK IT.
Main-Class: com.mindprod.Wassup.Wassup
Name: cmp/Wassup/Wassup$1.class
Digest-Algorithms: MD5 SHA1
MD5-Digest: VqONNAXcXR+ZRhTUeRQFjw==
SHA1-Digest: ZeKujl0SBvAlLpjN8NQIzh43cJs=
Name: cmp/Wassup/Wassup$2.class
Digest-Algorithms: MD5 SHA1
MD5-Digest: qPjkzkE3GQvNfI9NvFrj3A==
SHA1-Digest: tj7Ftc7psa6Rbq0NI7q6il2hwGs=
The specification document is very loose about the format of a manifest file.
Here are the rules I have gleaned from experimentation:
It might be wise to review the MANIFEST.MF file generated by examining the JAR
file with winzip. Unfortunately winzip
there are several problems in using winzip to
create jar files or to add files to them.
Main-Class
Starting with JDK 1.2, a jar may made be executable by designating one class in
it as the official class to start when the jar as a whole is executed, e.g.
double clicked or executed on the command line without a class mentioned:
java.exe -jar biorhythms.jar
The key is an attribute line in the meta-inf/manifest.inf
manifest member of the form:
Main-Class: com.mindprod.Bio.Biorhythms
Of course, the class selected must have a public static main
method. You can use the jar -m option to add that text
to your manifest from a main.mft file containing text
like this:
Main-Class: com.mindprod.Bio.Biorhythms
Watch out for extraneous lead/trailing spaces or extraneous trailing .class.
You must have a trailing linefeed or the main.mft file.
You can also specify the classpath, but you cannot specify command line
parameters or system propreties in the manifest.
Netscape 4.79's signtool.exe won't just sign an
existing jar file. You have to take your existing jar apart into separate files,
sign it, and let it recreate the jar file. Beware: the signtool
-m option uses an incompatible format for the main.mft
files that differs jar.exe's. A signtool-style
main.mft file needs a lead + sign on its entries. e.g.
+ Main-Class: com.mindprod.Wassup.Wassup
A jar.exe-style main.mft
does not.
In JDK 1.3+ there is an analogous entry to let you control the classpath.
Class-Path: myplace/myjar.jar . myplace/other.jar
Up until JDK 1.5, javac.exe ignored this entry. Note
the list is space-separated, not semicolon-separated as in the SET
CLASSPATH=C:\;. Note also that only relative directories and jar names
are permitted using / not \.
You cannot use C:\. This classpath has to be platform-independent.
If you use -jar on the java.exe
command line, java.exe will quietly ignore the
set environment classpath and any -classpath or -cp
command line options. What are you to do if you have additional jars to
include?
-
Copy them to the ext directory
-
Mention them in the Class-Path: manifest entry. If you
mention them in the manifest, you must specify the jars in relative URL form e.g.
myplace/myjar.jar and you must separate them by spaces,
not the usual Windows semicolons or Linux colons. You may only use relative URLs,
so drive letters are not permitted. The jar Class-Path will also be used for
Applets.
-
Mention these jars in a manifest extension list, and they will be downloaded if
needed. e.g.
Extension-List: activation mail
activation-Extension-Name: javax.activation
activation-Implementation-URL: http://abc.com/activation.jar
mail-Extension-Name: javax.mail
mail-Implementation-URL: http://abc.com/mail.jar
-
When Java goes searching for classes, it recursively searches the tree of jars
mentioned in the various Class-Path entries in the
already included jars. So you could create a dummy jar whose sole purpose was to
provide a list of other jars to search.
Writing To Jars
To write or update the Jar file, normally you use the jar.exe
utility. Since jars are just zip files with extra members, you can also use ZIP
utilites such as pkzip and winzip.
You can also read and write the jar files from Java with the ZipEntry,
ZipException, ZipFile, ZipInputStream
and ZipOutputStream classes. While a jar is in use,
some OS's may lock it, so don't count on being able to update jars on the fly
when you are executing classes from them.
Gotchas
It is easy to forget to include everything you need to make a jar totally self
contained. The jar will work on your machine because all the classes are
otherwise available. However, they won't work on your client's machine. I
suggest using Jet to check your jars to make sure they
are complete. You need to test the jar on a virgin machine to make sure all the
classes and resources are included.
When you recompile, naturally this does not magically update all the jars in the
world. Similarly when you build a jar, jar.exe will
happily include out of date class files that really should have been recompiled.
Make sure everything, including classes from other packages have been freshly
compiled before building your jar.
Sealing
A package within a jar file 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 to prevent tampering, or to prevent accidental use of
classes outside the original set.
To seal a package, you need to add a Name header for the package to your
manifest, followed by a Sealed header, like this:
Name: com/mindprod/myPackage/
Sealed: true
Learning More
Sun's Jar Reference : available: