Using the SecureClassLoader Class

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.