Summary The Access Controller

In order for this scheme to work, the Car class from www.ora.com must be loaded using a different class loader than that which loaded the Car class from www.sun.com. That way, when the virtual machine asks the class loader r2 for the definition of the Car class, it will get back correctly the definition from ora.com. The class loader does not need to be a different class; as this example implies, it must merely be a different instance of the class. Hence, applets that have a different codebase even if they originate on the same host are always loaded by different instances of the browsers class loader. Applets on the same page with the same codebase, however, may use the same class loader so that they may share class files as well as sharing other information. Some browsers also allow applets on different pages to be loaded by the same class loader as long as those applets have the same codebase, which is generally a more efficient and useful implementation. This differentiation between class files loaded from different class loaders occurs no matter what packages are involved. Dont be confused by the fact that there were no explicit package names given in our example. A large computer company might define a class named com.sun.Car , a large oil company might also define a class called com.sun.Car , and the two classes need to be considered as distinct classes −− which they will be if and only if they are loaded by different instances of the class loader. So far weve given a logical reason why the class loader is involved in the namespace resolution of Java classes. You might think that if everyone were to follow the convention that the beginning of their package name must be their Internet domain in reverse order −− e.g., com.sun for Sun Microsystems −− this idea of different class loaders wouldnt be necessary. But there are security reasons for this namespace separation as well. In Java, classes that are members of the same package have certain privileges that other classes do not have −− they can access all the classes of the package that have the default protection that is, the classes that are neither public , private , nor protected . Additionally, they can access any instance variable of classes in the package if the instance variable also has the default protection. As we discussed in Chapter 3, the ability to reference only those items to which a class has access is a key part of the security restrictions Java places on a program to ensure memory and API integrity. Lets assume that no class loader based package separation exists and that we rely on Sun Microsystems to name its classes com.sun.Car and so on. Everything would proceed reasonably, until we surf to www.EvilSite.org, where someone has placed a class called com.sun.DoSomethingEvil . Without the namespace separation introduced by the class loader, this class would suddenly have access to all the default and protected classes and to the default and protected variables of every class that had been downloaded from Sun. Worse, that site could supply a class called com.sun.Car with a much different implementation than Suns −− such that when the user metaphorically, of course applied the cars brakes, the new implementation sped up instead. Clearly, this is not a desirable situation. Note too that with a badly written class loader, the hackers at EvilSite.org have the potential to supply new classes to override the core classes of the Java API. When the class loader that loaded the applet from EvilSite is asked to provide the java.lang.String class, it must provide the expected version of that class and not some version from EvilSite.org. In practice, this is not a problem because the class loader is written to find and return the core class first. Without enforcement of the namespace separation that weve just outlined, there is no way to ensure that the hackers at EvilSite.org have not forged a class into the com.sun package. The only way to prevent such forgeries would be to require that every class be a signed class which authenticated that it did in fact come from sun.com or wherever its package name indicates that it should have come from. Authenticated classes certainly have their place in Javas security model, but it would be unmanageable to require that every site sign and authenticate every class on its site. Hence, the separation of classes based on the class loader that loaded them −− and the convention that applets on different pages are loaded by different class loaders −− has its benefits for Java security as well as solving a messy logistical problem. Well now look into the details of how the class loader actually works.

6.2 Class Loading Architecture

Well show some examples of how to create and use class loaders a bit later in this chapter. First, lets examine from a logical perspective how class loaders work. Class loaders are organized into a tree hierarchy. At the root of this tree is the system class loader. This class loader is also called the primordial class loader or the null class loader. It is used only to load classes from the core Java API. The system class loader has one or more children. It has at least one child; the URL class loader that is used to load classes from the classpath. It may have other direct children, though typically any other class loaders are children of the URL class loader that reads the classpath. An example class loader hierarchy is shown in Figure 6−2; this is the hierarchy that might exist within the Java Plug−in after it has loaded applets from both www.sun.com and www.ora.com. Figure 6−2. A class loader hierarchy The hierarchy comes into play when it is time to load a class. Classes are loaded in one of three ways: either explicitly by calling the loadClass method of a class loader, explicitly by calling the Class.forName method, or implicitly when they are referenced by an already−loaded class. In any case, a class loader is asked to load the class. In the first case, the class loader is the object on which the loadClass method is invoked. In the case of the forName method, the class loader is either passed to that method, or it is the class loader that loaded the class that is calling the forName method. The implicit case is similar: the class loader that was used to load the referencing class is also used to load the 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