Contents | Prev | Next | Index | The JavaTM Virtual Machine Specification |
CHAPTER 5
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 Class
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 CONSTANT_Class
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).
The 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:
NoClassDefFoundError
.
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 NoClassDefFoundError
.
class
file did not actually contain the desired class or interface, class or interface resolution throws a NoClassDefFoundError
.
class
file does not specify a superclass and is not the class
file for class Object
, class or interface resolution throws a ClassFormat-Error
.
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 VerifyError
.
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:
abstract
has an abstract
method, class resolution throws an AbstractMethodError
.
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 loadClass
is 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.
loadClass
is 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 IllegalAccessError
exception.
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 name_index
item
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_Fieldref
or 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:
NoSuchFieldError
.
IllegalAccessError
exception.
NoSuchMethodError
.
IllegalAccessError
exception.
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 CONSTANT_String
entry references.
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
true
.3
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
.
String
is created containing the sequence of Unicode characters represented by the CONSTANT_String
entry; that class instance is the result of resolution.
CONSTANT_Integer
or CONSTANT_Float
(§4.4.4), CONSTANT_Long
or 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.
2
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.
3
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 intern
method.
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]