The Artima Developer Community
Sponsored Link

Security and the Class Loader Architecture
Class Loaders in Java's Security Model
by Bill Venners
First Published in JavaWorld, August 1997

<<  Page 2 of 4  >>


Class loaders and name-spaces
For each class it loads, the JVM keeps track of which class loader -- whether primordial or object -- loaded the class. When a loaded class first refers to another class, the virtual machine requests the referenced class from the same class loader that originally loaded the referencing class. For example, if the virtual machine loads class Volcano through a particular class loader, it will attempt to load any classes Volcano refers to through the same class loader. If Volcano refers to a class named Lava, perhaps by invoking a method in class Lava, the virtual machine will request Lava from the class loader that loaded Volcano. The Lava class returned by the class loader is dynamically linked with class Volcano.

Because the JVM takes this approach to loading classes, classes can by default only see other classes that were loaded by the same class loader. In this way, Java's architecture enables you to create multiple name-spaces inside a single Java application. A name-space is a set of unique names of the classes loaded by a particular class loader. For each class loader, the JVM maintains a name-space, which is populated by the names of all the classes that have been loaded through that class loader.

Once a JVM has loaded a class named Volcano into a particular name-space, for example, it is impossible to load a different class named Volcano into that same name-space. You can load multiple Volcano classes into a JVM, however, because you can create multiple name-spaces inside a Java application. You can do so simply by creating multiple class loaders. If you create three separate name-spaces (one for each of the three class loaders) in a running Java application, then, by loading one Volcano class into each name-space, your program could load three different Volcano classes into your application.

A Java application can instantiate multiple class loader objects either from the same class or from multiple classes. It can, therefore, create as many (and as many different kinds of) class loader objects as it needs. Classes loaded by different class loaders are in different name-spaces and cannot gain access to each other unless the application explicitly allows it. When you write a Java application, you can segregate classes loaded from different sources into different name spaces. In this way, you can use Java's class loader architecture to control any interaction between code loaded from different sources. You can prevent hostile code from gaining access to and subverting friendly code.

Class loaders for applets
One example of dynamic extension with class loaders is the Web browser, which uses class loader objects to download the class files for an applet across a network. A Web browser fires off a Java application that installs a class loader object -- usually called an applet class loader -- that knows how to request class files from an HTTP server. Applets are an example of dynamic extension, because when the Java application starts, it doesn't know which class files the browser will ask it to download across the network. The class files to download are determined at run time, as the browser encounters pages that contain Java applets.

The Java application started by the Web browser usually creates a different applet class loader object for each location on the network from which it retrieves class files. As a result, class files from different sources are loaded by different class loader objects. This places them into different name-spaces inside the host Java application. Because the class files for applets from different sources are placed in separate name-spaces, the code of a malicious applet is restricted from interfering directly with class files downloaded from any other source.

Cooperation between class loaders
Often, a class loader object relies on other class loaders -- at the very least, upon the primordial class loader -- to help it fulfill some of the class load requests that come its way. For example, imagine you write a Java application that installs a class loader whose particular manner of loading class files is achieved by downloading them across a network. Assume that during the course of running the Java application, a request is made of your class loader to load a class named Volcano.

One way you could write the class loader is to have it first ask the primordial class loader to find and load the class from its trusted repository. In this case, since Volcano is not a part of the Java API, assume the primordial class loader can't find a class named Volcano. When the primordial class loader responds that it can't load the class, your class loader could then attempt to load the Volcano class in its custom manner, by downloading it across the network. Assuming your class loader was able to download class Volcano, that Volcano class could then play a role in the application's future course of execution.

To continue with the same example, assume that some time later a method of class Volcano is invoked for the first time, and that the method references class String from the Java API. Because it is the first time the reference is used by the running program, the virtual machine asks your class loader (the one that loaded Volcano) to load String. As before, your class loader first passes the request to the primordial class loader, but in this case, the primordial class loader is able to return a String class back to your class loader.

The primordial class loader most likely didn't have to actually load String at this point because, given that String is such a fundamental class in Java programs, it was almost certainly used before and therefore already loaded. Most likely, the primordial class loader just returned the String class that it had previously loaded from the trusted repository.

Since the primordial class loader was able to find the class, your class loader doesn't attempt to download it across the network; it merely passes to the virtual machine the String class returned by the primordial class loader. From that point forward, the virtual machine uses that String class whenever class Volcano references a class named String.

<<  Page 2 of 4  >>

Sponsored Links

Copyright © 1996-2018 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use