| Contents |Prev |Next |Index | The Java Virtual Machine Specification |
CHAPTER 5
The Java virtual machine dynamically loads(§2.17.2), links(§2.17.3), and initializes(§2.17.4) classes and interfaces. Loading is the process of finding the binary representationof a class or interface type with a particular name andcreating a class or interface from that binary representation. Linking is the process of taking a class or interface and combining it into the runtime state of the Java virtual machine so that it can be executed. Initialization of a class or interface consists of executing the class or interface initialization method<clinit>(§3.9).
In this chapter,Section 5.1 describes how the Java virtual machine derives symbolic references from the binary representation of a class or interface.Section 5.2 explains how the processes of loading, linking, and initialization are first initiated by the Java virtual machine.Section 5.3 specifies how binary representations of classes and interfaces are loaded by class loaders and how classes and interfaces are created. Linking is described inSection 5.4.Section 5.5 details how classes and interfaces are initialized. Finally,Section 5.6 introduces the notion of binding native methods.
Theconstant_pool table(§4.4) in the binary representation of a class or interface is used to construct the runtime constant pool upon class or interface creation(§5.3). All references in the runtime constant pool are initially symbolic. The symbolic references in the runtime constant pool are derived from structures in the binary representation of the class or interface as follows:
CONSTANT_Class_info structure(§4.4.1) in the binary representation of a class or interface. Such a reference gives the name of the class or interface in the form returned by theClass.getName method, that is:Class.getName method.CONSTANT_Fieldref_info structure(§4.4.2) in the binary representation of a class or interface. Such a reference gives the name and descriptor of the field, as well as a symbolic reference to the class or interface in which the field is to be found.CONSTANT_Methodref_info structure(§4.4.2) in the binary representation of a class or interface. Such a reference gives the name and descriptor of the method, as well as a symbolic reference to the class in which the method is to be found.CONSTANT_InterfaceMethodref_info structure(§4.4.2) in the binary representation of a class or interface. Such a reference gives the name and descriptor of the interface method, as well as a symbolic reference to the interface in which the method is to be found.constant_pool table:CONSTANT_String_info structure(§4.4.3) in the binary representation of a class or interface. TheCONSTANT_String_info structure gives the sequence of Unicode characters constituting the string literal.String. In addition, if the methodString.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,must have the value("a" + "b" + "c").intern()== "abc"
true.CONSTANT_String_info structure.String.intern has previously been called on an instance of classString containing a sequence of Unicode characters identical to that given by theCONSTANT_String_info structure, then the result of string literal derivation is a reference to that same instance of classString.String is created containing the sequence of Unicode characters given by theCONSTANT_String_info structure; that class instance is the result of string literal derivation. Finally, theintern method of the newString instance is invoked.CONSTANT_Integer_info,CONSTANT_Float_info,CONSTANT_Long_info, orCONSTANT_Double_infostructures (§4.4.4,§4.4.5) in the binary representation of a class or interface. Note thatCONSTANT_Float_info structures represent values in IEEE 754 single format andCONSTANT_Double_info structures represent values in IEEE 754 double format (§4.4.4,§4.4.5). The runtime constant values derived from these structures must thus be values that can be represented using IEEE 754 single and double formats, respectively.constant_pool table of the binary representation of a class or interface, theCONSTANT_NameAndType_info(§4.4.6) andCONSTANT_Utf8_info(§4.4.7) structures are only used indirectly when deriving symbolic references to classes, interfaces, methods, and fields, and when deriving string literals.public class methodvoidmain(String[]). The invocation of this method drives all furtherexecution. Execution of the Java virtual machine instructions constituting themain method may cause linking (and consequently creation) of additional classes and interfaces, as well as invocation of additional methods.In some implementations of the Java virtual machine the initial class could be provided as a command line argument, as in JDK releases 1.0 and 1.1. Alternatively, the initial class could be provided by the implementation. In this case the initial class might set up a class loader that would in turn load an application, as in the Java 2 SDK, Standard Edition, v1.2. Other choices of the initial class are possible so long as they are consistent with the specification given in the previous paragraph.
If C is not an array class, it is created by loading a binary representation of C (seeChapter 4, "The class File Format") using a class loader(§2.17.2). Array classes do not have an external binary representation; they are created by the Java virtual machine rather than by a class loader.
There are two types of class loaders: user-defined class loaders and the bootstrap class loader supplied by the Java virtual machine. Every user-defined class loader is an instance of a subclass of the abstract classClassLoader. Applications employ class loaders in order to extend the manner in which the Java virtual machine dynamically loads and thereby creates classes. User-defined class loaders can be used to create classes that originate from user-defined sources. For example, a class could be downloaded across a network, generated on the fly, or extracted from an encrypted file.
A class loader L may create C by defining it directly or by delegating to another class loader. If L creates C directly, we say that Ldefines C or, equivalently, that L is thedefining loader of C.
When one class loader delegates to another class loader, the loader that initiates the loading is not necessarily the same loader that completes the loading and defines the class. If L creates C, either by defining it directly or by delegation, we say that Linitiates loading of C or, equivalently, that L is aninitiating loader of C.
At run time, a class or interface is determined not by its name alone, but by a pair: its fully qualified name and its defining class loader. Each such class or interface belongs to a singleruntime package. The runtime package of a class or interface is determined by the package name and defining class loader of the class or interface.
The Java virtual machine uses one of three procedures to create class or interface C denoted by N:
First, the Java virtual machine determines whether the bootstrap class loader has already been recorded as an initiating loader of a class or interface denoted by N. If so, this class or interface is C, and no class creation is necessary.
Otherwise, the Java virtual machine performs one of the following two operations in order to load C:
Typically, a class or interface will be represented using a file in a hierarchical file system. The name of the class or interface will usually be encoded in the pathname of the file.
This phase of loading must detect the following error:
NoClassDefFoundError or an instance of one of its subclasses.Then the Java virtual machine attempts to derive a class denoted by N using the bootstrap class loader from the purported representation using the algorithm found inSection 5.3.5. That class is C.
loadClass method on L. The result of the invocation is C. The Java virtual machine then records that the bootstrap loader is an initiating loader of C(§5.3.4).First, the Java virtual machine determines whether L has already been recorded as an initiating loader of a class or interface denoted by N. If so, this class or interface is C, and no class creation is necessary.
Otherwise the Java virtual machine invokesloadClass(N ) on L.1 The value returned by the invocation is the created class or interface C. The Java virtual machine then records that L is an initiating loader of C(§5.3.4). The remainder of this section describes this process in more detail.
When theloadClass method of the class loader L is invoked with the name N of a class or interface C to be loaded, L must perform one of the following two operations in order to load C :
ClassFile structure(§4.1); it then must invoke the methoddefineClass of classClassLoader. InvokingdefineClass causes the Java virtual machine to derive a class or interface denoted by N using L from the array of bytes using the algorithm found inSection 5.3.5.loadClass method). The result of the invocation is C.If L has already been recorded as an initiating loader of an array class with the same component type as N, that class is C, and no array class creation is necessary. Otherwise, the following steps are performed to create C:
public.When a class or interface C = <N1, L1> makes a symbolic reference to a field or method of another class or interface D = <N2, L2> , the symbolic reference includes a descriptor specifying the type of the field, or the return and argument types of the method. It is essential that any type name N mentioned in the field or method descriptor denote the same class or interface when loaded by L1 and when loaded by L2.
To ensure this, the Java virtual machine imposesloading constraints of the form NL1 = NL2 during preparation(§5.4.2) and resolution(§5.4.3). To enforce these constraints, the Java virtual machine will, at certain prescribed times (see§5.3.1,§5.3.2,§5.3.3, and§5.3.5), record that a particular loader is an initiating loader of a particular class. After recording that a loader is an initiating loader of a class, the Java virtual machine must immediately check to see if any loading constraints are violated. If so, the record is retracted, the Java virtual machine throws aLinkageError, and the loading operation that caused the recording to take place fails.
Similarly, after imposing a loading constraint (see§5.4.2,§5.4.3.2,§5.4.3.3, and§5.4.3.4), the Java virtual machine must immediately check to see if any loading constraints are violated. If so, the newly imposed loading constraint is retracted, the Java virtual machine throws aLinkageError, and the operation that caused the constraint to be imposed (either resolution or preparation, as the case may be) fails.
The situations described here are the only times at which the Java virtual machine checks whether any loading constraints have been violated. A loading constraint isviolated if, and only if, all the following four conditions hold:
C '.class File Representationclass file format.LinkageError.This phase of loading must detect the following errors:
class file format (§4.1, pass 1 of§4.9.1), loading throws an instance ofClassFormatError.UnsupportedClassVersionError.2NoClassDefFoundError or an instance of one of its subclasses.Object as its direct superclass, which must already have been loaded. OnlyObject has no direct superclass.Any exceptions that can be thrown due to class or interface resolution can be thrown as a result of this phase of loading. In addition, this phase of loading must detect the following errors:
IncompatibleClassChangeError.ClassCircularityError.Any exceptions that can be thrown due to class or interface resolution can be thrown as a result of this phase of loading. In addition, this phase of loading must detect the following errors:
IncompatibleClassChangeError.ClassCircularityError.Verification must detect the following error:
VerifyError.During preparation of a class or interface C, the Java virtual machine also imposes loading constraints (§5.3.4). Let L1 be the defining loader of C. For each methodm declared in C that overrides a method declared in a superclass or superinterface Preparation may occur at any time following creation but must be completed prior to initialization. Resolution can be attempted on a symbolic reference that has already been resolved. An attempt to resolve a symbolic reference that has already successfully been resolved always succeeds trivially and always results in the same entity produced by the initial resolution of that reference. Subsequent attempts to resolve a symbolic reference that the Java virtual machine has previously unsuccessfully attempted to resolve always fails with the same error that was thrown as a result of the initial resolution attempt. Certain Java virtual machine instructions require specific linking checks when resolving symbolic references. For instance, in order for agetfield instruction to successfully resolve the symbolic reference to the field on which it operates it must complete the field resolution steps given inSection 5.4.3.2. In addition, it must also check that the field is not Linking exceptions generated by checks 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 resolution. Note that such exceptions, although described as part of the execution of Java virtual machine instructions rather than resolution, are still properly considered failure of resolution. The Java virtual machine instructionsanewarray,checkcast,getfield,getstatic,instanceof,invokeinterface,invokespecial,invokestatic,invokevirtual,multianewarray,new,putfield, andputstatic make symbolic references to the runtime constant pool. Execution of any of these instructions requires resolution of its symbolic reference. The following sections describe the process of resolving a symbolic reference in the runtime constant pool(§5.1) of a class or interface D. Details of resolution differ with the kind of symbolic reference to be resolved.5.4.3 Resolution
The process of dynamically determining concrete values from symbolic references in the runtime constant pool is known asresolution.static. If it is astatic field, a linking exception must be thrown.5.4.3.1 Class and Interface Resolution
To resolve an unresolved symbolic reference from D to a class or interface C denoted by N, the following steps are performed:IllegalAccessError.
This condition can occur, for example, if C is a class that was originally declared to bepublic but was changed to be non-public after D was compiled.
When resolving a field reference, field resolution first attempts to look up the referenced field in C and its superclasses:
NoSuchFieldError. Otherwise, if field lookup succeeds but the referenced field is not accessible(§5.4.4) to D, field resolution throws anIllegalAccessError.Otherwise, let <E, L1> be the class or interface in which the referenced field is actually declared and let L2 be the defining loader of D. Let T be the name of the type of the referenced field. The Java virtual machine must impose the loading constraint that TL1=TL2(§5.3.4).
When resolving a method reference:
IncompatibleClassChangeError.NoSuchMethodError. If method lookup succeeds and the method isabstract, but C is notabstract, method resolution throws anAbstractMethodError. Otherwise, if the referenced method is not accessible(§5.4.4) to D, method resolution throws anIllegalAccessError.Otherwise, let <E, L1> be the class or interface in which the referenced method is actually declared and let L2 be the defining loader of D. Let T0 be the name of the type returned by the referenced method, and let T1, ..., Tn be the names of the argument types of the referenced method. The Java virtual machine must impose the loading constraints TiL1=TiL2 for i = 0 to n(§5.3.4).
When resolving an interface method reference:
IncompatibleClassChangeError.Object, interface method resolution throws aNoSuchMethodError.public.public.protected and is declared in a class C, and D is either a subclass of C or C itself.protected or package private (that is, neitherpublic norprotected norprivate), and is declared by a class in the same runtime package as D.private and is declared in D.protected field access or method invocation (the target must be of class D or a subtype of D). That requirement is checked as part of the verification process(§5.4.1); it is not part of link-time access control.A class or interface may be initialized only as a result of:
Classor in packagejava.lang.reflect.native method is integrated into the Java virtual machine so that it can be executed. Although this process is traditionally referred to as linking, the term binding is used in the specification to avoid confusion with linking of classes or interfaces by the Java virtual machine.loadClass method of a class loader in order to cause it to load a class or interface. The argument toloadClass is the name of the class or interface to be loaded. There is also a two-argument version of theloadClass method. The second argument is aboolean that indicates whether the class or interface is to be linked or not. Only the two-argument version was supplied in JDK release 1.0.2, and the Java virtual machine relied on it to link the loaded class or interface. From JDK release 1.1 onward, the Java virtual machine links the class or interface directly, without relying on the class loader.2UnsupportedClassVersionError was introduced in the Java 2 platform, Standard Edition, v1.2. In earlier versions of the platform an instance ofNoClassDefFoundError orClassFormatError was thrown in case of an unsupported version depending on whether the class was being loaded by the system class loader or a user-defined class loader.
Virtual Machine Specification
Copyright © 1999 Sun Microsystems, Inc.All rights reserved
Please send any comments or corrections through ourfeedback form