|Contents | Prev | Next | Index
|The JavaTM Virtual Machine Specification
Java classes and interfaces are dynamically loaded (§2.16.2), linked (§2.16.3), and
initialized (§2.16.4). Loading is the process of finding the binary form of a class or
interface type with a particular name and constructing, from that binary form, a
object to represent the class or interface. Linking is the process of taking a binary
form of a class or interface type and combining it into the runtime state of the Java
Virtual Machine so that it can be executed. Initialization of a class consists of executing its static initializers and the initializers for static fields declared in the class.
The Java Virtual Machine performs most aspects of these procedures through operations on a constant pool (§4.4), a per-type runtime data structure that serves many of the purposes of the symbol table of a conventional language. For example, Java Virtual Machine instructions that might otherwise have been designed to take immediate numeric or string operands instead fetch their operands from the constant pool. Classes, methods, and fields, whether referenced from Java Virtual Machine instructions or from other constant pool entries, are named using the constant pool.
A Java compiler does not presume to know the way in which a Java Virtual Machine lays out classes, interfaces, class instances, or arrays. References in the constant pool are always initially symbolic. At run time, the symbolic representation of the reference in the constant pool is used to work out the actual location of the referenced entity. The process of dynamically determining concrete values from symbolic references in the constant pool is known as constant pool resolution. Constant pool resolution may involve loading one or more classes or interfaces, linking several types, and initializing types. There are several kinds of constant pool entries, and the details of resolution differ with the kind of entry to be resolved.
Individual Java Virtual Machine instructions that reference entities in the constant pool are responsible for resolving the entities they reference. Constant pool entries that are referenced from other constant pool entries are resolved when the referring entry is resolved.
A given constant pool entry may be referred to from any number of Java Virtual Machine instructions or other constant pool entries; thus, constant pool resolution can be attempted on a constant pool entry that is already resolved. An attempt to resolve a constant pool entry that has already been successfully resolved always succeeds trivially, and always results in the same entity produced by the initial resolution of that entry.
Constant pool resolution is normally initiated by the execution of a Java Virtual Machine instruction that references the constant pool. Rather than give the full description of the resolution process performed by Java Virtual Machine instructions in their individual descriptions, we will use this chapter to summarize the constant pool resolution process. We will specify the errors that must be detected when resolving each kind of constant pool entry, the order in which those errors must be responded to, and the errors thrown in response.
When referenced from the context of certain Java Virtual Machine instructions, additional constraints are put on linking operations. For instance, the getfield instruction requires not only that the constant pool entry for the field it references can be successfully resolved, but also that the resolved field is not a class (
static) field. If it is a class field, an exception must be thrown. Linking exceptions that are specific to the execution of a particular Java Virtual Machine instruction are given in the description of that instruction and are not covered in this general discussion of constant pool resolution. Note that such exceptions, although described as part of the execution of Java Virtual Machine instructions rather than constant pool resolution, are still properly considered failure of the linking phase of Java Virtual Machine execution.
The Java Virtual Machine specification documents and orders all exceptions that can arise as a result of constant pool resolution. It does not mandate how they should be detected, only that they must be. In addition, as mentioned in §6.3, any of the virtual machine errors listed as subclasses of
VirtualMachineError may be thrown at any time during constant pool resolution.
CONSTANT_Class (§4.4.1) represents a class or
interface. Various Java Virtual Machine instructions reference
entries in the constant pool of the class that is current upon their execution
(§3.6). Several other kinds of constant pool entries (§4.4.2) reference
CONSTANT_Class entries and cause those class or interface references to be
resolved when the referencing entries are resolved. For instance, before a
method reference (a
CONSTANT_Methodref constant pool entry) can be resolved,
the reference it makes to the class of the method (via the
class_index item of the
constant pool entry) must first be resolved.
If a class or interface has not been resolved already, the details of the resolution process depend on what kind of entity is represented by the
CONSTANT_Class entry being resolved. Array classes are handled differently from non-array classes and from interfaces. Details of the resolution process also depend on whether the reference prompting the resolution of this class or interface is from a class or interface that was loaded using a class loader (§2.16.2).
name_index item of a
CONSTANT_Class constant pool entry is a reference to a
CONSTANT_Utf8 constant pool entry (§4.4.7) for a UTF-8 string that represents the fully qualified name (§2.7.9) of the class or interface to be resolved. What kind of entity is represented by a
CONSTANT_Class constant pool entry, and how to resolve that entry, is determined as follows:
["), then the entry is a reference to a non-array class or to an interface.
["), then the entry is a reference to an array class. Array classes are resolved specially (§5.1.3).
has not been loaded yet, the Java Virtual Machine will search for a file C
.class and attempt to load class or interface C from that file. Note that there is no guarantee that the file C
.class will actually contain the class or interface C, or that the file C
.class is even a valid
class file. It is also possible that class or interface C might have already been loaded, but not yet initialized. This phase of loading must detect the following errors:
class file (pass 1 of §4.9.1), or is not a
class file of a supported major or minor version (§4.1), class or interface resolution throws a
class file did not actually contain the desired class or interface, class or interface resolution throws a
class file does not specify a superclass and is not the
class file for class
Object, class or interface resolution throws a
java.lang.Object as their superclass, which must already have been loaded.
class file C
.class does not satisfy the static or structural constraints on valid
class files listed in Section 4.8, "Constraints on Java Virtual Machine Code," class or interface resolution throws a
class file for class or interface C is successfully verified, the class or interface is prepared. Preparation involves creating the static fields for the class or interface and initializing those fields to their standard default values (§2.5.1). Preparation should not be confused with the execution of static initializers (§2.11); unlike execution of static initializers, preparation does not require the execution of any Java code. During preparation:
static). Such exceptions are still considered and documented to be linking, not runtime, exceptions.
Error or one of its subclasses, then a new instance of the class
ExceptionInInitializerError, with E as the argument, is created and used in place of E.
ExceptionInInitializerError but is unable to do so because an
Out-Of--Memory-Error occurs, then the
OutOfMemoryError object is thrown instead.
Illegal-Access-Error. This condition can occur, for example, if a class that is originally declared
public is changed to be
private after another class that refers to the class has been compiled.
loadClass method of
that class loader is invoked on the fully qualified path name (§2.7.9) of the class to
be resolved. The value returned by the
loadClass method is the resolved class. The
remainder of the section describes this process in more detail.
Every class loader is an instance of a subclass of the abstract class
ClassLoader. Applications implement subclasses of
ClassLoader in order to extend the manner in which the Java Virtual Machine dynamically loads classes. Class loaders can be used to create classes that originate from sources other than files. For example, a class could be downloaded across a network, it could be generated on the fly, or it could be decrypted from a scrambled file.
The Java Virtual Machine invokes the
loadClass method of a class loader in order to cause it to load (and optionally link and initialize) a class. The first argument to
loadClass is the fully qualified name of the class to be loaded. The second argument is a boolean. The value
false indicates that the specified class must be loaded, but not linked or initialized; the value
true indicates the class must be loaded, linked, and initialized.
Implementations of class loaders are required to keep track of which classes they have already loaded, linked, and initialized:2
loadClass method is invoked with the name of a class or interface that it has not yet loaded, the class loader must perform one of the following two operations in order to load the class or interface:
class file format; it then must invoke the method
defineClass of class
ClassLoader on those bytes to convert them into a class or interface with this class loader as the class loader for the newly defined class. Invoking
define-Class causes the Java Virtual Machine to perform step 1a of §5.1.1.
defineClass then causes the
loadClass method of the class loader to be invoked recursively in order to load the superclass of the newly defined class or interface. The fully qualified path name of the superclass is derived from the
super_class item in the
class file format. When the superclass is loaded in, the second argument to
false, indicating that the superclass is not to be linked and initialized immediately.
findSystemClass in class
ClassLoader with the fully qualified name of the class or interface to be loaded. Invoking this method causes the Java Virtual Machine to perform step 1 of §5.1.1. The resulting
class file is not marked as having been loaded by a class loader.
true the class or interface is linked and initialized. This second argument is always
true if the class loader is being called upon to resolve an entry in the constant pool of a class or interface. The class loader links and initializes a class or interface by invoking the method
resolveClass in the class
ClassLoader. Linking and initializing a class or interface created by a class loader is very similar to linking and initializing a class or interface without a class loader (steps 2-4 of §5.1.1):
First, the superclass of the class or interface is linked and initialized by calling the
loadClass method of the class loader with the fully qualified name of the superclass as the first argument, and
true as the second argument. Linking and initialization may result in the superclass's own superclass being linked and initialized. Linking and initialization of a superclass must detect any of the errors of step 3 of §5.1.1.
Next, the bytecode verifier is run on the class or interface being linked and initialized. The verifier may itself need classes or interfaces to be loaded, and if so, it loads them by invoking the
loadClass method of the same class loader with the second argument being
false. Since verification may itself cause classes or interfaces to be loaded (but not linked or initialized, to avoid circularity), it must detect the errors of step 1 of §5.1.1 for any classes or interfaces it attempts to load. Running the verifier may also cause the errors of step 3a of §5.1.1.
If the class file is successfully verified, the class or interface is then prepared (step 3b of §5.1.1) and initialized (step 4 of §5.1.1).
Finally, access permissions to the class or interface are checked (step 5 of §5.1.1). If the current class or interface does not have permission to access the class being resolved, class resolution throws an
If none of the preceding errors were detected, loading, linking, and initialization of the class or interface must have completed successfully.
CONSTANT_Class (§4.4.1) represents an array class
if the first character of the UTF-8 string (§4.4.7) referenced by the
of that constant pool entry is a left bracket ("
["). The number of initial consecutive
left brackets in the name represents the number of dimensions of the array class.
Following the one or more initial consecutive left brackets is a field descriptor
(§4.3.2) representing either a primitive type or a non-array reference type; this field
descriptor represents the base type of the array class.
The following steps are performed to resolve an array class referenced from the constant pool of a class or interface:
L"), that primitive type is the base type of the array class.
L"), that reference type is the base type of the array class. The reference type is itself resolved using the procedures indicated above in §5.1.1 or in §5.1.2.
CONSTANT_Fieldref (§4.4.2) represents a class or
instance variable (§2.9) or a (constant) field of an interface (§2.13.4). Note that
interfaces do not have instance variables. A constant pool entry tagged as
CONSTANT_Methodref (§4.4.2) represents a method of a class (a
static method) or of a
class instance (an instance method). References to interface methods are made using
CONSTANT_InterfaceMethodref constant pool entries; resolution of such entries is
described in §5.3.
To resolve a field reference or a method reference, the
CONSTANT_Class (§4.4.1) entry representing the class of which the field or method is a member must first be successfully resolved (§5.1). Thus, any exception that can be thrown when resolving a
CONSTANT_Class constant pool entry can also be thrown as a result of resolving a
CONSTANT_Methodref entry. If the
CONSTANT_Class entry representing the class or interface can be successfully resolved, exceptions relating to the linking of the method or field itself can be thrown. When resolving a field reference:
CONSTANT_InterfaceMethodref (§4.4.2) represents a
call to an instance method declared by an interface. Such a constant pool entry is
resolved by converting it into a machine-dependent internal format. No error or
exception is possible except for those documented in §6.3.
CONSTANT_String (§4.4.3) represents an instance of
a string literal (§2.3), that is, a literal of the built-in type
java.lang.String. The Unicode
characters (§2.1) of the string literal represented by the
CONSTANT_String entry are
found in the
CONSTANT_Utf8 (§4.4.7) constant pool entry that the
The Java language requires that identical string literals (that is, literals that contain the same sequence of Unicode characters) must reference the same instance of class
String. In addition, if the method
intern is called on any string, the result is a reference to the same class instance that would be returned if that string appeared as a literal. Thus,
("a" + "b" + "c").intern() == "abc"must have the value
To resolve a constant pool entry tagged
CONSTANT_String, the Java Virtual Machine examines the series of Unicode characters represented by the UTF-8 string that the
CONSTANT_String entry references.
CONSTANT_String and representing the identical sequence of Unicode characters has already been resolved, then the result of resolution is a reference to the instance of class
String created for that earlier constant pool entry.
intern has previously been called on an instance of class
String containing a sequence of Unicode characters identical to that represented by the constant pool entry, then the result of resolution is a reference to that same instance of class
String is created containing the sequence of Unicode characters represented by the
CONSTANT_String entry; that class instance is the result of resolution.
CONSTANT_Double (§4.4.5) all have values that are
directly represented within the constant pool. Their resolution cannot throw exceptions except for those documented in §6.3.
Constant pool entries that are tagged
CONSTANT_NameAndType (§4.4.6), and
CONSTANT_Utf8 (§4.4.7) are never resolved directly. They are only referenced directly or indirectly by other constant pool entries.
class files that have class loaders; it assumes that
class files loaded locally are trusted and do not need verification.
Future implementations may change the API between the Java Virtual Machine and the class
ClassLoader. Specifically, the Java Virtual Machine rather than the class loader will keep track of which classes and interfaces have been loaded by a particular class loader. One possibility is that the
loadClass method will be called with a single argument indicating the class or interface to be loaded. The virtual machine will handle the details of linking and initialization and ensure that the class loader is not invoked with the same class or interface name multiple times.
String literal resolution is not implemented correctly in Sun's JDK release 1.0.2. In that implementation of the Java Virtual Machine, resolving a
CONSTANT_String in the constant pool always allocates a new string. Two string literals in two different classes, even if they contained the identical sequence of characters, would never be
== to each other. A string literal could never be
== to a result of the
Contents | Prev | Next | Index
Java Virtual Machine Specification
Copyright © 1996, 1997 Sun Microsystems, Inc. All rights reserved
Please send any comments or corrections to [email protected]