Jar files

Jar file formats and jar tool (manifest, index):

Except for the addition of a Manifest file, a Jar file is just a zip archive.  A minimal manifest file is created automatically by the jar tool.  This file should have the name MANIFEST.MF in a sub-directory named META-INF.  Some other files, such as indexes, may also be present in that sub-directory.  Jar files are used to package Java class files, resources such as multi-media files, and even other Jars.  With the right manifest setting, a Jar file can be made executable by either double-clicking on it from some GUI, or running the command “java -jar nameOfJarfile”.  Jars with specific folders and files are used with application servers (web application Jars, or Enterprise Jars).  Such special-purpose Jar files may have different extensions than .jar, such as .war or .ear.

Jar files can contain packages and they can be listed on CLASSPATH.  Jars are used to hold JavaBeans, create clickable stand-alone applications, create signed classes (for extra security), and sealed packages (another security feature).  They enable you to bundle extra resources with your code, such as graphics, sound, fonts, and even other jar files.

Java jar files are compressed with zip.  However, the JDK includes the tool pack200, which repacks a jar file using a compression method designed for .class files, and can achieve a reported 90% reduction in Jar file size (I don’t see that myself).  That speeds downloads of applets and WebStart apps.  The jar tool can read such packed files as normal Jars.

The manifest file is a plain text file (that must end with a newline; so be careful when using notepad or similar editors that don’t automatically add a newline at the end).  It starts with a main section, followed by sections for files, packages, or URLs within the Jar, for which you want to add entries.  Each section is a list of manifest entries “name: value”.  All sections except the main (first) one start with a “Name:” entry.

To make a double-clickable jar, you need to add the (main) entry:

Main-Class: Name.of.class.with.main

to the main section (see jar -e main_class).  Some additional entries you may see or wish to use are:

·       Class-Path:

·       Implementation-Title:

·       Implementation-Version:

·       Implementation-Vendor:

·       Implementation-URL:

·       Sealed: true

·       Name:

·       Content-Type:

·       Java-Bean:

·       SplashScreen-Image:

(Some of these items are per section, which override the same entry from the main section.  See the JDK Documentation for jar for more details on the manifest file format.)

To add entries to the manifest file, you put the additional entries into a text file, and then use jar to merge your attributes into the (automatically generated) manifest.

The basic use of the jar tool (See jar tool JDK documentation for details) is:

 jar -{c|t|x|…}[-v]-f file [-m file] [-e main-class] \
    files_or_directories_to_include

Where you can use one action (-c to create, -x to extract, -t to view the contents) followed by various options.  Use -m file to specify a text file of additional manifest attributes to include.  Use -f file to name the Jar file.

Jar files can hold media, but this is tricky since the Applet.getCodebase() returns the URL of the jar file, not the URL of the media file within.  So you must be careful to use the getResource() method shown earlier.  (Older code often doesn’t!  Be careful when using example code from older books or the Internet.)

Class.getResource() and Class.getResourceAsStream() use the method Class.getClassLoader().getResource() internally.  Class.getClassLoader returns the ClassLoader that loaded some class.  However, it is possible in some cases for this to return the wrong class loader!  In general, to load resources that are contained in the jars included in a jnlp file of a jnlp application, or in Jar files listed on the archive attribute of a applet, you have to use the JNLPClassLoader, PluginClassLoader, or Plugin2ClassLoader that has the knowledge of those Jars.  (Note that Applets with different CODEBASEs may use different Classloaders even for the same class; it depends on the browser.)

A more reliable way to get resources is:
URL url = Thread.currentThread().
getContextClassLoader().getResource(".../pic.gif" );

To run a program in a Jar, double-click it, or run as java -jar file.jar.  Note that in this case, Java ignores the CLASSPATH.  It will only look in that Jar.  You need to set the Class-Path: list entry in the manifest (main section) instead.

The global CLASSPATH is an anachronism.  It is impossible to have one CLASSPATH that satisfies all possible compilations and all possible applications.  Installers will meddle with it.  Programs will work, then mysteriously stop working after you update something unrelated, that changes CLASSPATH.

Sealed Packages

Packages within JAR files can be optionally sealed.  This means that all classes defined in that package must be archived in the same JAR file.  This is a safety feature that prevents developers using the same package name in their own jar files, from accessing package-private members of your packages.

You might also want to seal a package to ensure version consistency among the classes in your software.

To seal all packages in a jar, you need to add this entry to the “main” section of the jar’s manifest:

Sealed: true

You can seal individual packages (when you have more than one per jar file), by putting that entry in one or more packages sections in the manifest.