Java application to load classes in custom ways.
Figure 1. Java's class loader architecture
A Java application can use two types of class loaders: a "primordial" class loader and class loader objects. The primordial class loader (there is only one of them) is a part of the JVM implementation. For example, if a JVM is implemented as a C program on top of an existing operating system, then the primordial class loader will be part of that C program. The primordial class loader loads trusted classes, including the classes of the Java API, usually from the local disk.
At run time, a Java application can install class loader objects that load classes in custom ways, such as by downloading class files across a network. The JVM considers any class it loads through the primordial class loader to be trusted, regardless of whether or not the class is part of the Java API. It views with suspicion, however, those classes it loads through class loader objects. By default, it considers them to be untrusted. While the primordial class loader is an intrinsic part of the virtual machine implementation, class loader objects are not. Instead, class loader objects are written in Java, compiled into class files, loaded into the virtual machine, and instantiated just like any other object. They really are just another part of the executable code of a running Java application. You can see a graphical depiction of this architecture in Figure 2.
Figure 2. Java's class loader architecture
Because of class loader objects, you don't have to know at compile-time all the classes that may ultimately take part in a running Java application. They enable you to dynamically extend a Java application at run time. As it runs, your application can determine what extra classes it needs and load them through one or more class loader objects. Because you write the class loader in Java, you can load classes in any manner: You can download them across a network, get them out of some kind of database, or even calculate them on the fly.
Class loaders and
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
perhaps by invoking a method in class
virtual machine will request
Lava from the class
loader that loaded
class returned by the class loader is dynamically linked with
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
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
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 canno