Sponsored Link •
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
from the class loader that loaded
Lava class returned by the class loader is dynamically
linked with class
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
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
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
Volcano. When the primordial class loader responds
that it can't load the class, your class loader could then attempt to
Volcano class in its custom manner, by
downloading it across the network. Assuming your class loader was able
to download class
could then play a role in the application's future course of
To continue with the same example, assume that some time later a method
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
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
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
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
returned by the primordial class loader. From that point forward, the
virtual machine uses that
String class whenever class
Volcano references a class named