Sponsored Link •
|
Advertisement
|
The part of a Java virtual machine implementation that takes care of finding and loading types is the class loader subsystem. Chapter 1, "Introduction to Java's Architecture," gives an overview of this subsystem. Chapter 3, "Security," shows how the subsystem fits into Java's security model. This chapter describes the class loader subsystem in more detail and show how it relates to the other components of the virtual machine's internal architecture.
As mentioned in Chapter 1, the Java virtual machine contains two kinds of class loaders: a bootstrap class loader and user-defined class loaders. The bootstrap class loader is a part of the virtual machine implementation, and user-defined class loaders are part of the running Java application. Classes loaded by different class loaders are placed into separate name spaces inside the Java virtual machine.
The class loader subsystem involves many other parts of the Java virtual machine and several classes
from the java.lang
library. For example, user-defined class loaders are regular Java
objects whose class descends from java.lang.ClassLoader
. The methods of
class ClassLoader
allow Java applications to access the virtual machine's class
loading machinery. Also, for every type a Java virtual machine loads, it creates an instance of class
java.lang.Class
to represent that type. Like all objects, user-defined class loaders
and instances of class Class
reside on the heap. Data for loaded types resides in the
method area.
The class loader subsystem is responsible for more than just locating and importing the binary data for classes. It must also verify the correctness of imported classes, allocate and initialize memory for class variables, and assist in the resolution of symbolic references. These activities are performed in a strict order:
Java virtual machine implementations must be able to recognize and load classes and interfaces stored in binary files that conform to the Java class file format. An implementation is free to recognize other binary forms besides class files, but it must recognize class files.
Every Java virtual machine implementation has a bootstrap class loader, which knows how to load trusted classes, including the classes of the Java API. The Java virtual machine specification doesn't define how the bootstrap loader should locate classes. That is another decision the specification leaves to implementation designers.
Given a fully qualified type name, the bootstrap class loader must in some way attempt to
produce the data that defines the type. One common approach is demonstrated by the Java virtual machine
implementation in Sun's 1.1 JDK on Windows98. This implementation searches a user-defined directory
path stored in an environment variable named CLASSPATH
. The bootstrap loader looks
in each directory, in the order the directories appear in the CLASSPATH
, until it finds a
file with the appropriate name: the type's simple name plus ".class
". Unless the type
is part of the unnamed package, the bootstrap loader expects the file to be in a subdirectory of one the
directories in the CLASSPATH
. The path name of the subdirectory is built from the
package name of the type. For example, if the bootstrap class loader is searching for class
java.lang.Object
, it will look for Object.class
in the
java\lang
subdirectory of each CLASSPATH
directory.
In 1.2, the bootstrap class loader of Sun's Java 2 SDK only looks in the directory in which the system
classes (the class files of the Java API) were installed. The bootstrap class loader of the implementation of
the Java virtual machine from Sun's Java 2 SDK does not look on the CLASSPATH
. In
Sun's Java 2 SDK virtual machine, searching the class path is the job of the system class
loader, a user-defined class loader that is created automatically when the virtual machine starts up.
More information on the class loading scheme of Sun's Java 2 SDK is given in Chapter 8, "The Linking
Model."
Although user-defined class loaders themselves are part of the Java application, four of the methods in
class ClassLoader
are gateways into the Java virtual machine:
// Four of the methods declared in class java.lang.ClassLoader: protected final Class defineClass(String name, byte data[], int offset, int length); protected final Class defineClass(String name, byte data[], int offset, int length, ProtectionDomain protectionDomain); protected final Class findSystemClass(String name); protected final void resolveClass(Class c);
Any Java virtual machine implementation must take care to connect these methods of class
ClassLoader
to the internal class loader subsystem.
The two overloaded defineClass()
methods accept a
byte
array, data[]
, as input. Starting at position
offset
in the array and continuing for length
bytes, class
ClassLoader
expects binary data conforming to the Java class file format--binary
data that represents a new type for the running application -- with the fully qualified name specified in
name
. The type is assigned to either a default protection domain, if the first version of
defineClass()
is used, or to the protection domain object referenced by the
protectionDomain
parameter. Every Java virtual machine implementation must
make sure the defineClass()
method of class ClassLoader
can cause a new type to be imported into the method area.
The findSystemClass()
method accepts a String
representing a fully qualified name of a type. When a user-defined class loader invokes this method in
version 1.0 and 1.1, it is requesting that the virtual machine attempt to load the named type via its bootstrap
class loader. If the bootstrap class loader has already loaded or successfully loads the type, it returns a
reference to the Class
object representing the type. If it can't locate the binary data for
the type, it throws ClassNotFoundException
. In version 1.2, the
findSystemClass()
method attempts to load the requested type from the system
class loader. Every Java virtual machine implementation must make sure the
findSystemClass()
method can invoke the bootstrap (if version 1.0 or 1.1) or
system (if version 1.2 or later) class loader in this way.
The resolveClass()
method accepts a reference to a
Class
instance. This method causes the type represented by the
Class
instance to be linked (if it hasn't already been linked). The
defineClass()
method, described previous, only takes care of loading. (See the
previous section, "Loading, Linking, and Initialization" for definitions of these terms.) When
defineClass()
returns a Class
instance, the binary file for the
type has definitely been located and imported into the method area, but not necessarily linked and initialized.
Java virtual machine implementations make sure the resolveClass()
method of
class ClassLoader
can cause the class loader subsystem to perform linking.
The details of how a Java virtual machine performs class loading, linking, and initialization, with user- defined class loaders is given in Chapter 8, "The Linking Model."
As mentioned in Chapter 3, "Security," each class loader maintains its own name space populated by the types it has loaded. Because each class loader has its own name space, a single Java application can load multiple types with the same fully qualified name. A type's fully qualified name, therefore, is not always enough to uniquely identify it inside a Java virtual machine instance. If multiple types of that same name have been loaded into different name spaces, the identity of the class loader that loaded the type (the identity of the name space it is in) will also be needed to uniquely identify that type.
Name spaces arise inside a Java virtual machine instance as a result of the process of resolution. As part of the data for each loaded type, the Java virtual machine keeps track of the class loader that imported the type. When the virtual machine needs to resolve a symbolic reference from one class to another, it requests the referenced class from the same class loader that loaded the referencing class. This process is described in detail in Chapter 8, "The Linking Model."
Sponsored Links
|