Skip to main content

The Java Extension Mechanism

April 26, 2005

{cs.r.title}









Contents
The Class Path
How User Classes Are Found
Sharing .jar Archives
Optional Packages
   Location of Optional Packages
   Sharing Optional Packages Among Java Runtimes
   Linux
   Windows
Tweaking the Manifest File
Pros and Cons of the Extension Mechanism
Conclusion
Resources

A huge number of publicly available packages extends the
functionality of the Java core platform. Some of them provide
access to features of the underlying operating system that are not
available through the standard class library, such as missing GUI
components, or reader and writer classes for important file formats.
Others are exciting technologies in their own right, like Spring,
Hibernate or Struts.

Sometimes installing them is a bit tricky, requiring you to
modify the class path of your application or tweak options passed to
the Java launcher. Others utilize a handy feature called the
Java Extension Mechanism. Libraries loaded via the
extension mechanism can be accessed by any Java program without
further prerequisites (besides copying some files to certain
directories). This article explains how the Extension Mechanism
works and discusses the steps required to implement your own
so-called optional packages.

The Class Path

The virtual machine uses the concept of a class path,
which is a set of directories and .zip or .jar archives. To find
classes (as well as other resources like properties files, images,
or audio content) the Java runtime looks in all locations specified
in the class path to find the required resource.

Early versions of Java relied heavily on an environment variable
called CLASSPATH that stored these locations. It is
easy to modify this variable, perhaps too easy: setting the class
path this way turned out to be error-prone, as changes usually
affected other applications. Another shortcoming of this approach
was the missing distinction between user (third-party) and system
classes. Today there is no need to use the CLASSPATH
environment variable.

Since Java 1.2, the virtual machine has distinguished between
three types of classes: bootstrap classes, extension
classes
, and user classes. Each type has its
own individual search path that can be modified separately. All three
parts together make up the class path. It is worth mentioning,
however, that the user class path is commonly referred to as simply
"the class path."

The difference between extension classes and user classes may
not be clear at first sight, as they both are implemented by
third-party developers, and hence do not belong to the core Java
classes. The difference is that user classes do not take advantage
of the extension mechanism. Additionally, the way that extension
classes are found by the virtual machine is different.

The boot class path specifies where core system classes are
searched. The system property sun.boot.class.path
stores these locations. It generally should not be necessary to
change them, but there is a non-standard option of the Java
launcher, -Xbootclasspath, that allows you to use
alternative core system classes.

How User Classes Are Found

The user class path specifies where user classes and resources
are searched. A simple program consisting of one class called
Test is invoked through:

[prettify]java Test
[/prettify]

This assumes you use the standard Java launcher. The class path
defaults to the current directory, so Test is
found easily (if the current directory contains
Test.class).

A program consisting of two .jars (the main application in
MyApp.jar and a set of utility classes in
MyUtils.zip) is invoked through:

[prettify]java -classpath MyApp.jar;MyUtils.zip myapp.MyAppMain
[/prettify]

The path separator is ; on Windows, while Unix
variants like Mac OS X and Linux use : instead.

Using -classpath completely overrides the default
setting; therefore, the current directory is not part of the class
path. Consequently, to access classes that are not part of the
specified .jar or .zip archives, the directory containing them must
be added to the user class path with the -classpath
option.

Sharing .jar Archives

It is common practice to have a Main-Class:
attribute in the main application .jar's manifest file so the
application can be launched by typing

java -jar
MyApp.jar
. In this case, the .jar file is the source for
all user classes. Any other class path option is
ignored.

To gain access to classes and resources stored in utility class
.jars, you must add a Class-Path: attribute to your
application's manifest file. Its value contains a space-delimited
list of relative URLs referencing libraries your application wishes
to use. These URLs are assumed to point to directories if they end
with the / character. Otherwise they are assumed to
refer to .jars.

To share a library among multiple projects, you could add its
location to the class paths of these programs using
-classpath or Class-Path: in the manifest
file of each program. This can be a cumbersome task if several
projects are involved. If we used the old-style
CLASSPATH environment variable, it would have been
sufficient to append the location of the library--no need to
explicitly reference it with each application wishing to use it.
But there must be a similar feature in recent Java versions,
right?

Optional Packages

The extension mechanism is a convenient and easy to use
infrastructure to provide optional packages.
These are sets of classes that extend the functionality of the
core platform. A key feature is that the virtual machine can find
components (we will see shortly what this means) of an optional
package without the need to explicitly mention it on the (user)
class path.

Optional packages consist of Java classes and other resources
like images, sounds, text, and property files. They are wrapped in a
.jar file that may be accompanied by platform-specific native code,
such as shared libraries and executables.

There are two flavors of optional packages, called
bundled and installed optional packages. If it is
bundled with an application, the library is provided at the same
code base and will therefore be downloaded automatically if
necessary. Installed optional packages are shared by all
applications using the same Java runtime environment.

Location of Optional Packages

There is nothing special about an optional package. To create
one, it is sufficient to bundle classes and resources into a .jar
archive. The only prerequisite is that the .jar must be copied to a
certain location inside of the Java runtime directory tree.

The location of optional packages can be determined and set
through system properties. Here is a small program that prints out
some interesting values.

[prettify]public class ShowProperties {
    
    public static void main(String[] args) {
        String [] properties = {
            "java.ext.dirs",
            "java.home",
            "path.separator",
            "file.separator",
            "java.library.path",
            "os.arch",
            "sun.boot.class.path"
        };
        for (int i = 0; i < properties.length; i++) {
            String key = properties[i];
            System.out.println(key + ": " + System.getProperty(key));
        }
    }
}
[/prettify]

The output of this program depends on the underlying operating
system, as seen in Figures 1-3.

Figure 1. Running ShowProperties on Mac OS X Panther
Figure 1. Running ShowProperties on Mac OS X Panther

Figure 2
Figure 2. Running ShowProperties on Linux--click for full-size image

Figure 2
Figure 3. Running ShowProperties on Windows--click for full-size image

java.home is a very important system property, as it
points to the base directory of the Java runtime.
path.separator contains the delimiter for search path
lists, as we have seen with the -classpath option.
file.separator contains the delimiter for files and
directories. In my examples here, I will use the backslash, but please keep
in mind that on Unix variants you must substitute it with the
slash. java.ext.dirs stores one or more directories to
be searched for optional packages. The default location is
java.home\lib\ext.

If an optional package requires native code, the Java runtime
looks in java.home\bin and
java.home\lib\ext\.
specifies the architecture for which the
native code has been compiled. It can be determined through the
os.arch system property. Please note that Windows and
Linux return different values, even when running on the same
machine. Pictures 2 and 3 were taken on a Toshiba notebook running
Windows Media Center Edition 2005 and SuSE Linux 9.2.

Installed optional packages are, by default, granted the same
security privileges as core platform classes, because they often
need to load and access native code. This can be modified by
editing the security policy configuration file called
java.policy, which is located in
java.home\lib\security.

Sharing Optional Packages Among Java Runtimes

So far, there is no standard procedure to make an optional
package system global; that is, to share it among Java runtimes. If
you have several versions of Java installed on your machine, you
need to copy all files associated with an optional package to the
ext directories of all Java installations. Undoubtedly,
this is a cumbersome task.

To solve this, you might pass -Djava.ext.dirs=... as
an additional argument when you invoke Java programs. As many
applications are launched through startup scripts or shortcuts, you
would need to modify all of them.

Apple offers a very nice solution to this problem. In Mac OS X,
you can throw .jars in /Library/Java/Extensions. The classes
will be visible in all Java runtimes.
/System/Library/Java/Extensions is reserved for Apple
extensions, and therefore should not be used by third-party
developers.

Fortunately, it is possible to simulate this behavior on other
operating systems.

Linux

On Linux, it is easy to achieve the same effect. You just need to
create symbolic links in the lib directories of the
Java installations you want to benefit from shared classes. These
links point to a directory that will contain the .jars.

  1. First, create a directory that will contain the shared
    optional packages; for example, /usr/java/extensions.
  2. cd to the lib directory of the Java
    installation you would like to have participate in the optional packages
    sharing.
  3. Rename the existing ext directory (
    mv ext
    ext.old
    ).
  4. Create the link as follows:
    ln -s
    /usr/java/extensions ext
    .
  5. Finally, check that access permissions, owner, and group are set
    correctly and that you have copied the files of the original
    ext directory (ext.old) to the newly
    created one.

From now on, any optional package you copy to
/usr/java/extensions will be visible to any Java
version you've modified as described.

Windows

Unfortunately, current versions of Windows do not support
symbolic links out of the box. The native NTFS file system
does, however, provide a similar concept, called
junctions, which is based upon NTFS reparse
points
. Sadly enough, typical Windows installations do not
contain tools to create them. but you can use a freeware tool by
Mark Russinovich called Junction. Please consult the
Resources section to download the
program.

With the Junction tool, it is easy to adapt the steps
described in the Linux section.

  1. First, create a directory that will contain shared
    optional packages; for example, C:\Program
    Files\Java\Extensions
    .
  2. Then you need to rename the ext directory to
    ext.old.
  3. The next step is to create a junction named ext
    that points to C:\Program Files\Java\Extensions. This
    is done as follows (please open cmd.exe):
    junction.exe C:\Programme\Java\jdk1.5.0\jre\lib\ext
    C:\Programme\Java\Extensions
    . The pathnames, of course,
    reflect my machine and need to be modified to meet your
    configuration. The first argument to junction.exe is
    the name of the junction to be created, which is the
    ext directory. The second argument specifies the
    directory this junction shall point to. In our case, this is the
    newly created directory that will contain all shared optional
    packages.

Follow these steps for all Java versions you would like
to have participate in optional packages sharing.

Tweaking the Manifest File

The manifest file of installed optional packages should contain
some attributes that describe the extension.

  • Extension-Name: should contain a name for the
    optional package, possibly the name of its main package.
  • Specification-Vendor: and
    Specification-Version: specify the vendor of the
    specification and the version number to which the optional package conforms. The Java documentation suggests
    Sun Microsystems,
    Inc
    and 1.0.
  • Implementation-Vendor-id: identifies the
    producer of the optional package. The examples suggest a naming
    scheme similar to packages; for example,
    de.thomaskuenneth.
  • Implementation-Vendor: contains the vendor
    name; for example, Thomas Kuenneth.
  • Implementation-Version: contains the version
    number of the optional package; for example,
    1.0.

An optional package should use these attributes to identify
itself. There is an additional set of attributes that should be
used for applets.

Pros and Cons of the Extension Mechanism

Installed optional packages are visible to any Java program in
the context of a runtime environment without the need to modify the
class path. They are very easy to install, as they just need to be
copied to certain directories. If you receive an enhanced or bug-fixed version, an existing program is easy to update, as you just
have to replace the library.

On the other hand, applications may no longer work correctly if a
new version of an optional package changes its behavior. This may
be the case if classes or methods are removed or method signatures
are modified without providing backwards-compatible versions.

So far, Sun has specified a versioning scheme for optional
packages only for applets. In this case, the Java plugin checks for
appropriate version numbers. For installed optional packages, no
versioning mechanism is applied.

Another point worth mentioning is that classes of optional
packages will be found prior to application classes, as they are
treated like core platform classes. The user class path is searched
last. So even if your application .jar contains a newer version of a
class, the class belonging to the optional package will be
used.

Conclusion

The Java extension mechanism offers an easy-to-use
infrastructure for providing optional packages. Packages can be
used by all Java programs without the need to modify the user
class path. Instead of requiring the user to work with the
-classpath option, please consider taking advantage of
the extension mechanism.

However, the current approach has some shortcomings, such as the
inability to share optional packages among Java installations.
Additionally, just like for applets, Sun needs to specify a
versioning scheme that ensures that applications will use the
appropriate version of an installed optional package.

Resources

width="1" height="1" border="0" alt=" " />
Thomas Kunneth works as a software architect at the German authorities, specializing in Java-based rich clients.
Related Topics >> Programming   |