This document describes the Java platform's new mechanism for
handling extensions. An extension is a group of packages
housed in one or more JAR files that
implement an API that extends the Java platform. Extension classes
extend the platform in the sense that the
virtual machine can find and load them without their being on the
class path, much as if they were classes in the platform's core API.
An implementation of an extension may consist of code written in the
Java programming language and, less
commonly, platform-specific native code. In addition, it may include
properties, localization catalogs, images, serialized data, and other
resources specific to the extension.
Support for extensions in browsers such as Internet Explorer and
Netscape Navigator is available through the Java Plug-in.
A standard extension is an implementation of an open,
standard API (examples of standard extensions from Sun are
JavaServlet,
Java3D, JavaManagement).
Most standard extension packages are rooted in the javax.*
namespace, although there may be exceptions.
The extension mechanism is designed to contain the following elements:
an extension or application packaged as a JAR file can declare
dependencies on other JAR files, thus allowing an application
to consist of multiple modules, and,
the class loading mechanism is augmented to search
installed extensions (and other libraries) for
classes, and, if that fails, to search along an
application-specified path for classes.
Applications must therefore, in general, be prepared to specify and
supply the extensions (and, more generally, libraries) that
it needs. The system will prefer installed copies of
extensions (and libraries) if they exist; otherwise, it will delegate
to the class loader of the application to find and load the
referenced extension (and library) classes.
This architecture, since it allows applications, applets and servlets
to extend their own class path, also permits packaging and deploying
these as multiple JAR files.
Each extension or application consists of at least one JAR file containing
an optional manifest, code and assorted resources. As described below,
this primary JAR file can also include additional information in its
manifest to describe dependencies on other JAR files. The jar
command line tool included with the JDK software provides a convenient means of
packaging extensions, although any ZIP-compatible archiving tool
should work as well. (See the reference pages for the jar
tool: [Win32][Solaris])
An extension or application may refer to additional JAR files which will
be referenced from the primary JAR, and these can optionally contain
their own dependency information as well.
Packages comprising extensions should be named per the standard package
naming conventions when implementing extensions.
These conventions are outlined in The Java Language Specification,
but the requirement that the domain prefix be specified in all upper case
letters has been removed. For example, the package name com.sun.server
is an accepted alternative to COM.sun.server. Unique package
naming is recommended in order to avoid conflicts, because applications
and extensions may share the same class loader.
An extension may either be bundled with an application or
installed in the JRE for use by all applications. Bundled
extensions are provided at the same code base as the application and
will automatically be downloaded in the case of network applications
(applets). For this reason, bundled extensions are often called
download extensions. Installed extensions are loaded when first used and
will be shared by all applications running in the JRE.
When packaging extensions, the JAR file manifest can be used to
identify vendor and version information (see The Java Versioning Specification).
Classes for installed extensions are shared by all code in the same
Java 1.2 virtual machine. Thus, installed extensions are similar to
the platform's core classes (in rt.jar), but with an associated
class loader and a pre-configured security policy as described below.
Classes for bundled extensions are private to the class loader of the
application, applet or servlet. In the case of network applications such
as applets, these extensions will be automatically downloaded as needed.
Since class loaders are currently associated with a codebase, this permits
multiple applets originating from the same codebase to share implementations
(JARs).
Bundled Extensions
The manifest for an application or extension can specify one or more
relative URLs referring to the JAR files and directories for the extensions
(and other libraries) that it needs. These relative URLs will be treated
relative to the code base that the containing application or extension JAR
file was loaded from.
An application (or, more generally, JAR file) specifies the relative
URLs of the extensions (and libraries) that it needs via the manifest
attribute Class-Path. This attribute lists the URLs to search
for implementations of extensions (or other libraries) if they cannot be
found as extensions installed on the host Java virtual machine.
These relative URLs may include JAR files and directories for any
libraries or resources needed by the application or extension. Relative
URLs not ending with '/' are assumed to refer to JAR files. For example,
Multiple Class-Path headers may be specified, and are combined
sequentially.
Currently, the URLs must be relative to the code base of the JAR
file for security reasons. Thus, remote extensions will originate from
the same code base as the application. A future enhancement will leverage
the facilities of the Java 1.2 Security APIs to allow references to JAR
files at other URLs.
Each relative URL is resolved against the code base that the containing
application or extension was loaded from. If the resulting URL is invalid
or refers to a resource that cannot be found then it is ignored.
The resulting URLs are used to extend the class path for the application,
applet, or servlet by inserting the URLs in the class path immediately
following the URL of the containing JAR file. Any duplicate URLs are omitted.
For example, given the following class path:
a.jar b.jar
If extension b.jar contained the following Class-Path
manifest attribute:
Class-Path: x.jar a.jar
Then the resulting application class path would be the following:
a.jar x.jar b.jar
Of course, if x.jar had dependencies of its own then these
would be added according to the same rules and so on for each subsequent
URL. In the actual implementation, JAR file dependencies are processed
lazily so that the JAR files are not actually opened until needed.
Installed Extensions
In Sun's implementation of the Java 1.2 virtual machine, the JAR files
of a installed extension are placed in a standard local code source
Here <java-home> refers to the directory where the
runtime software is installed (which is the top-level directory of the JRE
or the jre directory in the JDK software), and <arch>
refers to the Solaris processor architecture (sparc or
i386).
A installed extension may additionally contain one or more shared
libraries (such as .dll files) and executables.
Native libraries may
also be placed in jre/lib/ext/<arch> for both Win32 and
Solaris, where <arch> will be i386 on Win32
systems. The jre/lib/ext/<arch> directory is
searched afterjre\bin (win32) or
jre/lib/<arch> (Solaris).
Currently, an extension that contains native code cannot be downloaded
by network code, whether such code is trusted or not, into the virtual
machine at execution time. An extension that contains native code and
is bundled with a network application must be installed in the JRE or
JDKTM software.
By default, installed extensions in this standard directory are trusted.
That is, they are granted the same privileges as if they were core platform
classes (those in rt.jar). This default privilege is specified
in the system policy file, but can be overridden for a particular extension
by adding the appropriate policy file entry.
Note also that if a installed extension JAR is signed by a trusted
entity, then it will be granted the privileges associated with the
trusted signer.
Other locations for installed extensions can be specified through
the system property java.ext.dirs. This property specifies
one or more directories to search for installed extensions, each
separated by File.pathSeparatorChar. The default setting for
this property is the standard directory for installed extensions indicated
above.
Extension Sealing
JAR files and packages can be optionally sealed, so that an
extension or package can enforce consistency within a version.
A package sealed within a JAR specifies that all classes defined
in that package must originate from the same JAR. Otherwise, a
SecurityException is thrown.
A sealed JAR specifies that all packages defined by
that JAR are sealed unless overridden specifically for a package.
A sealed package is specified via the new manifest attribute,
Sealed, whose value is true or false
(case irrelevant). For example,
Name: javax/servlet/internal/
Sealed: true
specifies that the javax.servlet.internal package is sealed,
and that all classes in that package must be loaded from the same JAR file.
If this attribute is missing, the package sealing attribute is that of
the containing JAR file.
A sealed JAR is specified via the same new manifest header, Sealed,
with the value again of either true or false. For example,
Sealed: true
specifies that all packages in this archive are sealed unless explicitly
overridden for a particular package with the Sealed
attribute in a manifest entry.
If this attribute is missing, the module is assumed to not be sealed,
for backwards compatibility. The system then defaults to examining
package headers for sealing information.
Package sealing is also important for security, because it restricts
access to package-protected members to only those classes defined in
the package that originated from the same JAR file. For example,
in the runtime JAR rt.jar all of the standard core Java packages
with the exception of packages sun.io and
java.text.resources are sealed.
Package sealing is checked for installed as well as downloaded
extensions, and will result in a SecurityException if violated.
Also, the null package is not sealable, so classes that are to be sealed
must be placed in their own packages.
Extension Security
The code source for a installed extension (namely
<java-home>/lib/ext) has a pre-configured security policy
associated with it. In Sun's implementation, the exact level of trust granted
to JARs in this directory is specified by the standard security policy
configuration file
<java-home>/lib/security/java.policy
The default policy is for a installed extension to behave
the same way it would if were part of the core platform.
This follows from the common need for a installed extension to
load native code.
The Java 1.2 Security Model provides some safety when installed
extension code is called from untrusted code. However extension code must
be carefully reviewed for potential security breaches wherever it uses privileged blocks.
A remotely loaded extension that needs to use access-checked system
services (such as file I/O) to function correctly must either be
signed by a trusted entity or loaded from a trusted source.
Consult the Java 1.2 security documentation for further details
regarding how to write extension and application code to use the new
security features.
API Details
The following classes have been changed or added in the 1.2 platform to
support the new extensions mechanism:
This class has been updated to support the new class loader delegation
model for loading classes and resources. The class loader delegation
model allows a "parent" class loader to be specified which will always
be searched first when loading a class or resource before attempting
to load it locally. New class loader implementations override the methods
findClass and findResource in order to specify
how classes and resources are loaded locally.
The following methods have been changed or added to support the new
delegation model:
getSystemClassLoader
Returns the system class loader for delegation. This is the
default delegation parent for new ClassLoader instances, and
is typically the class loader used to start the application.
loadClass
If the class has already been loaded then just return it.
Otherwise, try loading the class from the parent class loader
(or virtual machine's built-in class loader, called the
bootstrap class loader, if no parent was specified). If still
not found, then call the method findClass to load
the class locally.
findClass
Looks in this class loader for the specified class. This method
should be overridden in new class loader implementations. Its
default implementation throws ClassNotFoundException.
getResource
Try fetching the resource from the parent class loader (or bootstrap
class loader if no parent was specified). If still not found, then
call the method getLocalResource to load the resource
locally.
findResource
Looks in this class loader for the specified resource. This method
should be overridden by new class loader implementations. Its
default implementation returns null.
getResources
Returns an enumeration of all the resource URLs matching the
specified resource name. This enumeration includes all of the
matched resources of the parent class loader followed by the
enumeration returned by findResources.
findResources
Returns an enumeration of all the local resource URLs matching
the given name. This method should be overridden by new class
loader implementations. Its default implementation returns
null.
The new delegation model provides a consistent and well defined search
policy for loading classes and resources that simplifies class loader
implementation. These changes are backward compatible and will not affect
existing class loader implementations. However, applications that wish to
create their own class loaders and use extensions must use the new delegation
model.
The following example demonstrates a simple network class loader:
public class NetClassLoader extends ClassLoader {
URL url;
public NetClassLoader(URL url, ClassLoader parent) {
super(parent);
this.url = url;
}
protected Class findClass(String name)
throws ClassNotFoundException
{
.. load class from URL ...
}
protected URL findResource(String name) {
try {
URL u = new URL(url, name);
if (u.openConnection() != null) {
return u;
} else {
return null;
}
} catch (java.net.MalformedURLException mue) {
// handle exception
} catch (java.io.IOException ioe) {
// handle exception
}
}
}
This example will search the parent class loader (or bootstrap class loader,
if no parent was specified) for classes and resources before checking the
given URL. Classes and resources will be loaded according to the new
delegation model as described above.
This class has been changed to include two new methods for accessing
information about sealed packages. The method isSealed
can be used to check if a package has been sealed, in which case it will
return true. A second form of this method takes a URL and
will return true if the package is sealed with respect to
the specified URL. This can be used to in class loader implementations
to keep track of currently sealed packages when loading new classes.
This class provides the basic class loader support for extensions and
applications. It overrides both the findClass and
findResource methods to search one or more base URLs
for classes and resources. The search is lazy, such that a URL is not
opened until needed.
URLClassLoader manages a search path of URLs that is used
to load classes and resources. Initially, this is set to the URLs
specified when the class loader was created, but can be extended by
Class-Path manifest attribute as described above.
URLClassLoader supports all of the manifest attributes for
versioning specified in The Java Versioning Specification.
In addition, the following main manifest attributes are supported:
Main-Class: <classname> (no default)
Specifies the main class of an application. This is used
for invoking an application JAR file.
Class-Path: <urls..> (no default)
Local search path of relative JAR and directory URLs for loading
classes and resources. URLs not ending in '/' are assumed to refer
to JAR files.
Sealed: <true|false>
(default false)
All of the packages defined in this JAR file, with the exception
of the "null" package, are sealed. The "null" package can never be
sealed. This header can also be used to seal individual packages.
The java command has been changed in version 1.2 of
the JRE and JDK software in order to
support stand-alone applications that use extensions. Previously,
application classes had been loaded from the system class loader.
In the new java command, an instance of URLClassLoader
is created to load the application. The delegation parent is set to
to the shared class loader maintained by the system for loading installed
extensions. The resulting application class loader will then handle
loading both installed and bundled extensions for the application.
The property java.class.path is read to obtain the search
path of URLs to use when creating the instance of URLClassLoader
to load the application. This specifies the application's class path for
loading application classes and resources. When loading a class or
resource, the class loader will first search the system class path, then
installed extensions, and finally the application class path.
A consequence of this change is that the property java.class.path
no longer includes entries from the bootstrap class path. The system class
path can now be obtained separately from the system property
sun.boot.class.path.
The CLASSPATH environment variable specifies the default value of
the property java.class.path. If this environment variable
is not set, then the default value for java.class.path is
set to the current directory.
The option -classpath is now shorthand for setting the
java.class.path property. Formerly, this option was used to
override the search path for system classes. In the new java
command there is no longer any need to set the system class path.
The option -cp which had previously been part of only the
jre command has now been added to java as well.
Since it is no longer necessary to prepend the system class path
this option is now merely an alias for -classpath.
For example, the following command usages are all equivalent:
By default, applications are invoked without a security manager so
that no policy checking is enabled. This is compatible with the
previous command behavior where everything was loaded from the system
class path.
To install a security manager when invoking an application, use the
-Djava.security.manager command-line option:
java -Djava.security.manager Foo
The default system policy file resides at
{java.home}/lib/security/java.policy. Individual users may
augment this with policy files located at {user.home}/.java.policy.
To specify a policy file to be used in addition to these default
policies, use:
For conveniently running applications packaged in JAR files the new
-jar option has been added to the java application-launcher
tool. This allows applications in JAR
files to be executed directly using the java command.
When using the -jar option the java.class.path property
is set to the JAR file being executed, which overrides any other definition
specified via the -classpath or -cp command-line options.
The JAR file's manifest is then consulted to find the name of the application's
main class specified via the Main-Class manifest attribute.
For example, if the manifest for server.jar contained the
following attribute:
Main-Class: com.sun.server.Main
then server.jar could be executed using either of the following:
On Win32 systems the Java 2 runtime environment's installation program
will register a default association for JAR files so that double-clicking
a JAR file on the desktop will automatically run it with javaw -jar.
Dependent extensions bundled with the application will also be loaded
automatically. This feature makes the end-user runtime environment
easier to use on Win32 systems.
The Solaris 2.6 kernel has already been extended to recognize the
special "magic" number that identifies a JAR file, and to invoke
java -jar on such a JAR file as if it were a native Solaris
executable. A application packaged in a JAR file can thus be
executed directly from the command line or by clicking an icon on
the CDE desktop.
The jre command is obsolete for JRE 1.2 and has been merged
with the java tool. The only environment variable still used
is CLASSPATH and this can now be overridden by using the
java tool's
-classpath or -cp option. The -cp option
which used to prepend the system class path in the JRE is now identical
to -classpath in the new java command.
Applications which install their own class loaders or security managers
may not be able to run under the new java command until they are updated
for version 1.2 of the platform. These applications must be updated to
use the new security features and delegation class loader introduced in
the 1.2 JRE and JDK software.
For compatibility we still provide the old-style launcher behavior
in the command oldjava which can be used to run applications
from the system class path as in version 1.1 of the Java platform.
However, extensions are
not supported with the oldjava command.