Transferred from:http://blog.csdn.net/ns_code/article/details/17881581
Class loading process
Class starts from being loaded into the virtual machine's memory, and its entire lifecycle includes: load, validate, prepare, parse, initialize, use, and unload seven phases, until the memory is unloaded. The order in which they begin is as follows:
The process of loading, validating, preparing, parsing, and initializing five stages of the class load. In these five phases, the order in which the four phases of loading, validating, preparing, and initializing occurs is deterministic, and the parsing phase is not necessarily, which in some cases can begin after the initialization phase, in order to support runtime bindings for the Java language (also become dynamic or late bound). Also note that the stages here are started in order, rather than sequentially or in order , because these phases are usually mixed in a cross-section, often invoking or activating another phase during one phase of execution.
Here is a brief description of the bindings in Java: Binding refers to associating a method's invocation with the class (method body) where the method resides, and for Java, the bindings are divided into static and dynamic bindings:
- Static bindings: That is, pre-binding. The method is already bound before the program executes, and is implemented by the compiler or other linker. For Java, a simple binding that can be understood as the program's compile time. In Java, only Final,static,private and constructor methods are pre-bound.
- Dynamic binding: That is, late binding, also called run-time binding. Binds at run time based on the type of the specific object. In Java, almost all methods are late-bound.
The following details the work done at each stage of the class loading process. Loading
During the first stage of the load-time class loading process, the virtual machine needs to complete the following three things during the load phase :
1. Get the binary byte stream defined by the fully qualified name of a class.
2. Transform the static storage structure represented by this byte stream into the runtime data structure of the method area.
3. Generate a Java.lang.Class object representing this class in the Java heap as the access entry for the data in the method area.
Note that the binary byte stream in 1th here is not simply taken from the class file, such as it can be obtained from the jar package, obtained from the network (the most typical application is the applet), generated by other files (JSP application), etc.
In contrast to other stages of class loading, the load phase (accurately, the action of getting the binary byte stream of a class during the load phase) is the strongest stage, because developers can either use the system-provided classloader to complete the load or customize their own classloader to complete the load.
When the load phase is complete, the binary byte stream outside the virtual machine is stored in the method area in the format required by the virtual machine, and an object of the Java.lang.Class class is created in the Java heap so that the data in the method area can be accessed through the object.
When it comes to loading, we have to mention the class loader, and the following is a concrete class loader.
Class Loader
Although the ClassLoader is only used to implement the load action of a class, its role in Java programs is far from being limited to the load phase of classes. For any class, it needs to be determined by its class loader and the class itself to be unique in the Java virtual machine, that is, even if two classes originate from the same class file, the two classes must be unequal if the classloader loading them is different. The "equality" here includes the return results of equals (), IsAssignableFrom (), Isinstance (), and so on, which represent the class object, and the result of the decision to use the INSTANCEOF keyword for the object's owning relationship.
in terms of the Java Virtual machine, there are only two different classloader:
- Start the ClassLoader: it is implemented in C + + (hotspot only, which is the default virtual machine after JDK1.5, there are many other virtual machines that are implemented in the Java language) and are part of the virtual machine itself.
- All other ClassLoader: These classloader are implemented by the Java language, independent of the virtual machine, and all inherit from the abstract class Java.lang.ClassLoader, which need to be loaded into memory by the startup ClassLoader before they can load other classes.
From the Java Developer's point of view, the class loader can be roughly divided into the following three categories:
- Start class loader: Bootstrap ClassLoader, same as above. It is responsible for loading the class libraries (such as Rt.jar, all java.* that are stored in the Jdk\jre\lib (JDK represents the JDK's installation directory, the same below), or in the path specified by the-xbootclasspath parameter, and can be recognized by the virtual machine. The classes that begin are loaded by bootstrap ClassLoader). The startup ClassLoader cannot be referenced directly by a Java program.
- Extension class loader: Extension ClassLoader, which is implemented by Sun.misc.launcher$extclassloader, is responsible for loading the Jdk\jre\lib\ext directory, or all class libraries in the path specified by the JAVA.EXT.DIRS system variable (such as classes beginning with javax.*), developers can use the extension class loader directly.
- Application ClassLoader: Application ClassLoader, which is implemented by Sun.misc.launcher$appclassloader, is responsible for loading the class specified by the user class path (ClassPath). Developers can use the ClassLoader directly, if the application does not customize its own classloader, typically this is the default class loader in the program.
Applications are loaded with each other by these three kinds of loaders, and if necessary, we can also add a custom class loader. Because the JVM's own ClassLoader only knows how to load the standard Java class file from the local file system, if you write your own classloader, you can do the following :
1) The digital signature is automatically validated before the non-confidence code is executed.
2) dynamically create custom build classes that meet user-specific needs.
3) Obtain Java class from a specific location, such as in a database and in a network.
In fact, when using applets, a specific classloader is used, because Java class needs to be loaded from the network, and the relevant security information is checked, and the application server is mostly using custom ClassLoader technology.
The hierarchical relationships of these kinds of loaders are as follows:
This hierarchical relationship is known as the parent-delegation model of the ClassLoader. We call the class loader above each layer the parent loader of the current layer ClassLoader, and of course, parent-child relationships between them are not implemented through inheritance, but instead use the combination of relationships to repeat the code in the parent loader. The model was introduced during JDK1.2 and is widely used in almost all Java programs, but it is not a mandatory constraint model, but rather a class loader implementation that Java designers recommend to developers.
The workflow of the parent delegation model is that if a classloader receives a request for a class load, it does not attempt to load the class on its own, but instead delegates the request to the parent loader to complete, then up, so that all class load requests should eventually be passed to the top-level startup class loader. The load cannot be completed until the parent loader finds the required class in its search scope, and the child loader tries to load the class on its own.
The obvious benefit of using the parental delegation model to organize the relationship between ClassLoader is that the Java class has a hierarchy of priorities along with its classloader (plainly, the directory in which it resides), which is important to ensure the stable operation of the Java program. For example, class Java.lang.Object classes are stored in jdk\jre\ Lib under the Rt.jar, so no matter which class loader to load this class, will eventually be delegated to the startup ClassLoader to load, this way to ensure that the object class in the program in the various class loaders are the same class.
Validation
The purpose of the validation is to ensure that the byte stream in the class file contains information that conforms to the requirements of the current virtual machine and does not compromise the security of the virtual machine itself. Implementations of different virtual machines for class validation may vary, but the following four phases of validation are generally performed: file format validation, metadata validation, bytecode validation, and symbolic reference validation.
- File format validation: Verify that the byte stream conforms to the class file format specification, and can be processed by the current version of the virtual machine, the main purpose of this verification is to ensure that the input byte stream can be correctly parsed and stored in the method area. After this phase of validation, the byte stream is stored in the memory's method area, and the subsequent three validations are based on the storage structure of the method area.
- Metadata validation: Semantic validation of the metadata information of a class (in fact, the syntax check of each data type in the Class), ensuring that there is no metadata information that does not conform to the Java syntax specification.
- Bytecode verification: The main task of this phase verification is to conduct data flow and control flow analysis, to verify the method body of the class, to ensure that the method of the class being validated will not make the behavior that endangers the virtual machine security at runtime.
- Symbol Reference Validation: This is the last stage of validation, which occurs when a virtual machine converts a symbolic reference to a direct reference (the conversion occurs during the parsing phase, which is explained later), and is primarily a matching check for information other than the class itself (a variety of symbol references in a constant pool).
Prepare
The prep phase is a phase that formally allocates memory for class variables and sets the initial value of class variables, which are allocated in the method area. There are a few things to note about this phase:
1. This time memory allocation includes only class variables (static), not instance variables, and instance variables are allocated to the Java heap as objects are instantiated when the object is instanced.
2, the initial value set here is usually the default value of the data type 0 (such as 0, 0L, NULL, FALSE, etc.), rather than being explicitly assigned in the Java code value.
3. If the Constantvalue attribute exists in the field attribute table of the class field, which is both final and static, then in the prepare phase the variable value is initialized to the value specified by the Constvalue property.
parsingThe parsing phase is the process by which a virtual machine converts a symbolic reference in a constant pool into a direct reference. The differences and associations between symbolic references and direct references have been compared in the class file structure article , and are not described here. It is said that the parsing phase may start before initialization, or it may start after initialization, and the virtual opportunity is judged by the need to parse the symbolic reference in the constant pool (before initialization) when the class is loaded, or until a symbolic reference is to be used before parsing it (after initialization). A common thing to do with multiple parsing requests for the same symbol reference is that the virtual machine implementation may cache the results of the first parse (direct references are recorded in the run-time pool, and the constants are marked as resolved), thus avoiding repetitive parsing actions. The parsing action is mainly for class or interface, field, class method, interface method Four kinds of symbol reference, corresponding to Constant_class_info, Constant_fieldref_info, constant_methodref_ in constant pool, respectively. Info, constant_interfacemethodref_info four types of constants.
- parsing of classes or interfaces: determine whether the direct reference to be converted is an array type or a reference to an ordinary object type for different parsing.
- Field Resolution: When parsing a field, first find in this class whether it contains a field with a simple name and a field descriptor that matches the target, and if so, the end of the search, and if not, the individual interfaces and their parent interfaces implemented by the class are searched recursively from top to bottom, not yet, The parent class is recursively searched from top to bottom according to the inheritance, until the lookup is over, and the lookup process looks like this:
Finally, it is important to note that in theory the search is parsed in the order described above, but in practice, the compiler implementation of the virtual machine may be more stringent than the above specification requirements. If a field with the same name appears in both the interface and the parent class of the class, or if it appears in both the interface of itself or the parent class, the compiler may refuse to compile.
3, class method parsing: The parsing of the class method and the search procedure for the field resolution is similar, just more to judge the method is in the class or interface steps, and the class method matching search, is to search the parent class, then search the interface.
4, interface method parsing: Similar to the class method parsing steps, the knowledge interface will not have a parent class, so only recursively search the parent interface. Initialize
Initialization is the last step in the class loading process, and at this stage, the Java program code defined in the class is really starting to execute. In the preparation phase, the class variable has been assigned the initial value of the system requirement, and during the initialization phase, the class variables and other resources are initialized according to the subjective plan specified by the programmer through the program.
Class initialization is the last phase of the class loading process, and in the initialization phase, the Java program code in the class is actually started. The virtual machine specification strictly specifies that there are only four cases in which the class must be initialized immediately:
- When you encounter the four bytecode directives of new, getstatic, putstatic, Invokestatic, if the class has not yet been initialized, you need to trigger its initialization first. The most common Java code scenario for generating these four instructions is when instantiating an object with the New keyword, when reading or setting a static field (static) of a class (except for static fields that have been put into the constant pool at compile time by static decoration and final decoration), And when a static method of a class is called.
- When you use the Java.lang.refect package method to make a reflection call to a class, you need to trigger its initialization first if the class has not yet been initialized.
- When initializing a class, it is necessary to trigger the initialization of its parent class if it finds that its parent class has not yet been initialized.
- When the virtual machine starts, the user needs to specify a main class to execute, and the virtual opportunity executes the main class first.
The virtual machine specifies that only these four cases will trigger the initialization of the class, known as an active reference to a class, except that all references to the class do not trigger its initialization, called a passive reference.
Summary
Throughout the class loading process, except in the load phase, where the user application can customize the class loader participation, all the rest of the action is completely dominated and controlled by the virtual machine. The Java program code (and bytecode) defined in the class is started before initialization, but the execution code here is only the beginning and it is limited to the <clinit> () method. The class loading process is mainly to load the class file (exactly, the binary byte stream of the classes) into the virtual machine memory and actually execute the bytecode operation before it really starts after the load is complete.
Java Virtual machine--class loading mechanism