Sponsored Link •
The previous chapter described in detail the format of the Java class file, the standard binary form for representing Java types. This chapter looks at what happens when binary type data is imported into a Java virtual machine. The chapter follows the lifetime of a type (class or interface) from the type's initial entrance into the virtual machine to its ultimate exit. It discusses the processes of loading, linking, and initialization that occur at the beginning of a type's lifetime; the processes of object instantiation, garbage collection, and finalization that can occur in the prime of a type's lifetime; and the unloading that can occur at the end of a type's lifetime.
The Java virtual machine makes types available to the running program through a process of loading, linking, and initialization. Loading is the process of bringing a binary form for a type into the Java virtual machine. Linking is the process of incorporating the binary type data into the runtime state of the virtual machine. Linking is divided into three sub-steps: verification, preparation, and resolution. Verification ensures the type is properly formed and fit for use by the Java virtual machine. Preparation involves allocating memory needed by the type, such as memory for any class variables. Resolution is the process of transforming symbolic references in the constant pool into direct references. Implementations may delay the resolution step until each symbolic reference is actually used by the running program. After verification, preparation, and (optionally) resolution are completed, the type is ready for initialization. During initialization, the class variables are given their proper initial values. See Figure 7-1 for a graphical depiction of this process.
As you can see from Figure 7-1, the processes of (1) loading, (2) linking, and (3) initialization must take place in that order. The only exception to this required ordering is the third phase of linking, resolution, which may optionally take place after initialization.
The Java virtual machine specification gives implementations flexibility in the timing of class and interface loading and linking, but strictly defines the timing of initialization. All implementations must initialize each class or interface on its first active use. The following six situations qualify as active uses:
newinstruction. Alternatively, via implicit creation, reflection, cloning, or deserialization.)
finaland initialized by a compile-time constant expression (in bytecodes, the execution of a
Classor in classes in the
main()<method) when a Java virtual machine starts up
All other uses of a type besides the six listed here are passive uses, which don't trigger an initialization of the type. Several examples illustrating the difference between active and passive uses are given later in this chapter.
As mentioned in the previous list, initialization of a class requires prior initialization of its superclass. Applied recursively, this rule means that all of a class's superclasses must be initialized prior to the initialization of the class. The same is not true, however, of interfaces. An interface is initialized only because a non-constant field declared by the interface is used, never because a subinterface or class that implements the interface needs to be initialized. Thus, initialization of a class requires prior initialization of all its superclasses, but not its superinterfaces. Initialization of an interface does not require initialization of its superinterfaces.
The "initialize on first active use" rule drives the mechanism that loads, links, and initializes classes. On its first active use, a type must be initialized. Before it can be initialized, however, it must be linked. And before it can be linked, it must be loaded. At their option, implementations may load and link types early. They need not wait until the type's first active use to load and link the type. If a type hasn't been loaded and linked before its first active use, however, it must be loaded and linked at that time, so that it can be initialized.