The Class Loader and Namespaces

referenced class. Class loaders are responsible for asking their parent to load a class; only if that operation fails will the class loader attempt to define the class itself. Take the case of the class com.sun.Car that was loaded by the URL class loader that knows about www.sun.com. When that Car class references the java.lang.String class, the same URL class loader will be asked to provide the String class object. It will ask its parent the URL class loader for the classpath to provide that class. Its parent will in turn ask the system class loader to provide that class. Since the system class loader knows about the java.lang.String class, it will return the appropriate class. Note, however, that if the com.sun.Car class references the com.ora.Ferrari class, class loading will fail: the class loader that is associated with www.ora.com is not in the ancestor path of the class loader that is associated with www.sun.com. The net effect of this is that system classes will always be loaded from the system class loader, classes on the class path will always be loaded by the class loader that knows about the classpath, and in general, a class will be loaded by the oldest class loader in the ancestor hierarchy that knows where to find a class. When you create a class loader, you can insert it anywhere into the hierarchy of class loaders except at the root. Typically, when a class loader is created, its parent is the class loader of the class that is instantiating the new class loader.

6.3 Implementing a Class Loader

Now well look at how to implement a class loader. The class loader we implement will be able to extend the normal permissions that are granted via policy files, and it will enforce certain optional security features of the class loader.

6.3.1 Class Loader Classes

The basic class that defines a class loader is the ClassLoader class java.lang.ClassLoader : public abstract class ClassLoader Turn a series of Java bytecodes into a class definition. This class does not define how the bytecodes are obtained but provides all other functionality needed to create the class definition. However, the preferred class to use as the basis of a class loader is the SecureClassLoader class java.security.SecureClassLoader : public class SecureClassLoader extends ClassLoader Turn a series of Java bytecodes into a class definition. This class adds secure functionality to the ClassLoader class, but it still does not define how bytecodes are obtained. Although this class is not abstract, you must subclass it in order to use it. The secure class loader provides additional functionality in dealing with code sources and protection domains. You should always use this class as the basis of any class loader you work with; in fact, the ClassLoader class would be private were it not for historical reasons. There is a third class in this category: the URLClassLoader class java.net.URLClassLoader : public class URLClassLoader extends SecureClassLoader Load classes securely by obtaining the bytecodes from a set of given URLs. 102 If youre loading classes through the filesystem or from an HTTP server, then the URLClassLoader provides a complete definition of a class loader. In addition, you can override some of its methods if you want to modify the security policy of classes that it defines.

6.3.2 Key Methods of the Class Loader

The ClassLoader class and its subclasses have three key methods that you work with when creating your own class loader.

6.3.2.1 The loadClass method

The loadClass method is the only public entry into the class loader: public Class loadClassString name Load the named class. A ClassNotFoundException is thrown if the class cannot be found. This is the simplest way to use a class loader directly: it requires that the class loader be instantiated and then be used via the loadClass method. Once the Class object has been constructed, there are three ways in which a method in the class can be executed: A static method of the class can be executed. This is the technique the Java virtual machine uses to execute the main method of a Java application once the initial class has been loaded, but this is not generally a technique used by Java applications. • An object of the class can be constructed using the newInstance method of the Class class, but only if the class has an accessible constructor that requires no arguments. Once the object has been constructed, methods with well−known signatures can be executed on the object. This is the technique that a program like appletviewer uses: it loads the initial class of the applet, constructs an instance of the applet which calls the applets no−argument constructor, and then calls the applets init method among other methods. It is also used by factory classes throughout Java. • The reflection API can be used to call a static method on the class or to construct instances of the object and execute methods on that object. The reflection API allows more flexibility than the second choice since it allows arguments to be passed to the constructor of the object. • In addition, every time that a class needs the definition of any other class, it calls the loadClass method of its class loader. The correct implementation of the loadClass method is crucial to the security of the virtual machine. For instance, one operation this method performs is to call the parent class loader to see if it has already defined a particular class; this allows all the core Java classes to be loaded by the primordial class loader. If that operation is not performed correctly, security could suffer. As a developer you should be careful when you override this method; as an administrator, this is one of the reasons to prevent untrusted code from creating a class loader.

6.3.2.2 The findClass method

The loadClass method performs a lot of setup and bookkeeping related to defining a class, but from a developer perspective, the bulk of the work in creating a Class class object is performed by the findClass method: protected Class findClassString name Load the class specified in the name parameter. The name will be the fully−qualified package name of the class e.g., java.lang.String . Chapter 6. Java Class Loaders The findClass method uses whatever mechanism it deems appropriate to load the class e.g., by reading a class file from the file system or from an HTTP server. It is then responsible for creating the protection domain associated with the class and using the next method to create the Class class object.

6.3.2.3 The defineClass methods

These methods all take an array of Java bytecodes and some information that specifies the permissions associated with the class represented by those bytecodes. They all return the Class class object: protected final Class defineClassString name, byte[] b, int off, int len throws ClassFormatError protected final Class defineClassString name, byte[] b, int off, int len, ProtectionDomain protectionDomain throws ClassFormatError protected final Class defineClassString name, byte[] b, int off, int len, CodeSource cs throws ClassFormatError Create a class based on the bytecodes in the given array. The protection domain associated with the class varies based on which form is used: In the first method, the class is assigned to the default protection domain. ◊ In the second method, the class is assigned to the given protection domain. ◊ In the third method, the protection domain is defined by the class loader based on the given code source. ◊ The third method in this list is available only within the SecureClassLoader class and its subclasses including the URLClassLoader class. When you use that method, the class loader will ask what permissions are associated with a particular code source by calling this method: protected PermissionCollection getPermissionsCodeSource cs Return the permissions that should be associated with the given code source. The default implementation of this method calls the getPermissions method of the Policy class. Note that this gives you two effective ways in which to override the policy set up by policy files: by supplying your own Policy class or by supplying your own secure class loader that overrides this method.

6.3.3 Responsibilities of the Class Loader

When you implement a class loader, you override some or all of the methods weve just listed. In sum, the class loader must perform the following steps: The security manager is consulted to see if this program is allowed to access the class in question. If it is not, a security exception is thrown. This step is optional; it should be implemented at the beginning of the loadClass method. This corresponds to the use of the accessClassInPackage permission. 1. If the class loader has already loaded this class, it finds the previously defined class object and returns that object. This step is built into the loadClass method. 2. Otherwise, the class loader consults its parent to see if the parent knows how to load the class. This is a recursive operation, so the system class loader will always be asked first to load a class. This prevents programs from providing alternate definitions of classes in the core API but a clever class loader can defeat that protection. This step is built into the loadClass method. 3. The security manager is consulted to see if this program is allowed to create the class in question. If it is not, a security exception is thrown. This step is optional; if implemented, it should appear at the 4. 104