The appletviewer
and Java Plug−in define their own class loader, which is an extension of the URL class loader. This class loader extends to classes loaded from a file URL the permissions to open a connection to
and accept a connection from the localhost. Classes loaded from an HTTP URL have the same permissions as those granted in the URL class loader.
The only other publicly−accessible class loader in the core API is the RMI class loader. There is a class called RMIClassLoader
java.rmi.server.RMIClassLoader which, despite its name, is neither a class
loader nor restricted to RMI. This class has a static method called loadClass
which, like the loadClass
method of the ClassLoader
class, finds the named class and defines it. It uses an internal class loader to do this; the internal class loader happens to be a modification of the
URLClassLoader class. The URL used by this class loader is specified by the
java.rmi.server.codebase property; it uses the same permissions as a standard URL class loader. If
the features of this class loader meet your requirements, you can use it in any program, regardless of whether your program uses RMI.
6.4 Miscellaneous Class Loading Topics
There are a few details about class loaders that we havent yet covered. These details are not directly related to the security aspects of the class loader, which is why weve saved them until now. If youre interested in the
complete details of the class loader, well fill in the last few topics here.
6.4.1 Delegation
As weve mentioned, class loading follows a delegation model. This model permits a class loader to be instantiated with this constructor:
protected ClassLoaderClassLoader parent Create a class loader that is associated with the given class loader. This class loader delegates all
operations to the parent first: if the parent is able to fulfill the operation, this class loader takes no action. For example, when the class loader is asked to load a class via the
loadClass method,
it first calls the loadClass
method of the parent. If that succeeds, the class returned by the delegate will ultimately be returned by this class. If that fails, the class loader then uses its original
logic to complete its task, something like this:
public Class loadClassString name { Class cl;
cl = delegate.loadClassname; if cl = null
return cl; else continue with the loadClass logic
}
You may retrieve the delegate associated with a class loader with the following method. public final ClassLoader getParent
Return the class loader to which operations are being delegated. The class loader that exists at the root of the class loader hierarchy is retrieved via this method:
public static ClassLoader getSystemClassLoader 110
Return the system class loader the class loader that was used to load the base application classes. If a security manager is in place, you must have the
getClassLoader runtime permission to use this
method.
6.4.2 Loading Resources
A class loader can load not only classes, but any arbitrary resource: an audio file, an image file, or anything else. Instead of calling the
loadClass method, a resource is obtained by invoking one of these
methods: public URL getResourceString name
public InputStream getResourceAsStreamString name public URL findResourceString name
Find the named resource and return either a URL reference to it or an input stream from which it can be read. Implementations of class loaders should look for resources according to their internal rules,
which are typically but need not be the same rules as are used to find classes.
The getResource
method calls the getSystemResource
method; if it does not find a system resource, it returns the object retrieved by a call to the
findResource method which
by default will be null
. The getResourceAsStream
method simply calls the getResource
method and, if a resource is found, opens the stream associated with the URL. public static URL getSystemResourceString name
public static InputStream getSystemResourceAsStreamString name Find the named resource and return either a URL reference to it or an input stream from which it can
be read. By default, these methods look for the resource on the classpath and return that resource if found.
public final Enumeration getResourcesString name public Enumeration findResourcesString name
Return an enumeration of resources with the given name. In the first method, an enumeration of the local resources of all delegated class loaders including the present class loader is returned; in the
second method, only the local resources of the present class loader are returned.
6.4.3 Loading Libraries
Loading classes with native methods creates a call to this method of the ClassLoader
class: protected String findLibraryString libname
Return the directory from which native libraries should be loaded. This method is used by the
System.loadLibrary method to determine the directory in which the
native library in question should be found. If this method returns null
the default, the native library must be in one of the directories specified by either the
java.library.path or
java.sys.library.path property; typically, these properties are set in a platform−specific way e.g., from the
LD_LIBRARY_PATH on Solaris or the
PATH on Microsoft Windows.
However, custom class loaders can override that policy and require that libraries be found in some application−defined location. This prevents a user from overriding the runtime environment to specify an
alternate location for that library, which offers a slight security advantage. Note that if the user can write to the hardwired directory where the library lives, this advantage no longer exists: the user can simply overwrite
the existing library instead of changing an environment variable to point to another library; the end result is the same.
6.5 Comparison with Previous Releases
In Java 2, version 1.3, no class loader can define a class that is in the java package i.e., whose class name begins with
java . In 1.2 and earlier releases, that restriction is not present unless you code it into your own
class loader. Thats one reason why there is no class loader that uses the checkPackageDefinition
method although that method was not used in 1.2 either. In Java 1.1, class loading was significantly different. To begin, there are no code source or protection domain
objects in 1.1, and classes do not carry associated permissions with them. Security in 1.1 is solely up to the security manager, and the class loader simply loads classes.
That means that the loadClass
method in 1.1 is very different. In particular, there is only one defineClass
method that it can call the one without a protection domain argument, and it does not call the
findClass method. In order to write a class loader in 1.1, you must override the
loadClass method and perform all your work in that method. We show an example of this in
Appendix D. The secure class loader and URL class loader were introduced in Java 2, version 1.2. In 1.1, the primordial
class loader is used to load all classes on the classpath in addition to the classes in the core API. Delegation was also introduced in Java 2, version 1.2. In 1.1, a custom class loader can make a special method
call to load classes from the classpath, but there is no general hierarchy of class loaders. In 1.1, the default behavior of the methods that retrieve resources is to return
null .
The RMI class loader does not exist in Java 1.0.
6.6 Summary
The class loading mechanism is integral to Javas security features. Typically this integration is considered in light of the relationship between the class loader, the access controller, and the security manager. However,
the class loader is important in its own right. The class loader must enforce the namespace separation between classes that are loaded from different sites especially when these different sites are untrusted; this helps to
enforce the security mechanisms of the Java language.
For sites that need a more flexible security policy, a custom class loader may be desirable. Custom class loaders allow the security policy to be modified as classes are defined; this is similar to and compatible with
providing a new implementation of the Policy
class. However, custom class loaders can bypass the policy class altogether, which means that they can define immutable security policies though, of course, installing
the class loader in the first place still requires that applications have the appropriate policy−based permissions. In certain circumstances, this is easier than modifying and installing a new
Policy class.