Sponsored Link •
One of the primary reasons Java technology is a "good fit" for networks is that it has a comprehensive security model designed into its architecture. Beginning with a refresher on the Java sandbox, this article turns to one aspect of that security model: the class loader architecture of the Java virtual machine.
This month's article continues the discussion of Java's security model begun in last month's "Under the Hood," which provided a general overview of the security mechanisms built into the Java virtual machine (JVM). I also looked closely at one aspect of those security mechanisms: the JVM's built-in safety features. This month's article takes a look at yet another aspect of the JVM's built-in security mechanisms: the class loader architecture.
Java's security model is focused on protecting end-users from hostile programs downloaded from untrusted sources across a network. To accomplish this goal, Java provides a customizable "sandbox" in which Java programs run. A Java program can do anything within the boundaries of its sandbox, but it can't take any action outside those boundaries. The sandbox for untrusted Java applets, for example, prohibits many activities, including:
By making it impossible for downloaded code to perform certain actions, Java's security model protects users from the threat of hostile code. For more information on the sandbox concept, see last month's "Under the Hood."
The class loader
One aspect of the JVM that plays an important role in the security sandbox is the class loader architecture. In the JVM, class loaders are responsible for importing binary data that defines the running program's classes and interfaces. In the block diagram shown in Figure 1, a single mysterious cube identifies itself as "the class loader," but in reality, there may be more than one class loader inside a JVM. Thus, the class loader cube of the block diagram actually represents a subsystem that may involve many class loaders. The JVM has a flexible class loader architecture that allows a 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