Detailed explanation of the class loading process

Class loading has a total of three phases: load -> connect (validate -> prepare -> resolve) -> initialize.

The Java Virtual Machine specification does not specify when a load operation is appropriate. But for the initialization phase, the virtual machine strictly stipulates that the initialization operation will start in 5 cases (then the loading and connection operations must be performed first):

1. Encounter new, getstatic, putstatic or invokestatic. These three instructions respectively use the new keyword to instantiate an object, read or set a static field, and call the static method of the class.

2. Use the methods of the java.lang.reflect package to make reflection calls to the class. Such as: Class.forName(""), after this, if the class is not initialized, then its initialization needs to be triggered first.

3. When initializing a class, if it is found that the parent class is not initialized, first trigger the initialization of the parent class

4. When the virtual machine starts, the user needs to specify a main class to be executed (the class containing the main() method), and the virtual machine first initializes this main class

5. When using the dynamic language support of jdk1.7, because I am not familiar with this aspect, I will not go into details.

Because of these situations, the initialization process of the class will inevitably be triggered, so the loading and connection operations must be performed first. Now take Student student = new Student() as an example:

When the program encounters the new instruction, it will initialize the Student class. If the initialization operation has been performed, then the object can be created directly in the heap. If it is not initialized, the loading will be executed.

During the loading phase, the virtual machine mainly completes the following three things:

1. Obtain the binary stream that defines this class through the fully qualified name of a class. (That is, it can be obtained directly from the class file, or from the zip package, or even from the network)

2. Convert 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 the class in memory as the access entry for various data of this class in the method area.

After the loading phase is completed, the compile-time constant pool in the class file is converted into the runtime constant pool in the method area, and a Class object representing the Student class is instantiated in the method area.

Next, the connection operation starts, and the connection process is divided into three stages: verification, preparation, and analysis:

Verification : Mainly verify whether the current class file conforms to the specifications of the virtual machine to ensure that it does not pose a threat to the virtual machine

Preparation : Formally allocate memory and set initial values ​​(0 values ​​for various data types) for class variables. These class variables are stored in the method area, as follows:

private static String name = "wsh";

Then at this time, memory is allocated for the name variable in the method area, and the initial value is set to null.

But if the class variable is defined as follows:

private static final String name = "wsh"

Then at this stage, the initial value will be set directly to a reference to the address of the string "wsh" in the constant pool.

Parsing : The parsing phase is mainly the process of replacing symbolic references in the constant pool with direct references. (not very familiar with this process)

When all connection operations are completed, the initialization operation begins. Initialization is also the last step in the class loading process. In the previous class loading phase, all actions are basically performed autonomously by the virtual machine, but in the initialization phase, the system will initialize class variables and other resources according to the programmer's wishes, such as for

        private static String name = "wsh"

After the connection operation is completed, the name points to a null, but in the initialization phase, the system will perform the initialization operation for the name variable, so that the variable saves a reference to the string "wsh" in the execution constant pool.

At this point, all class loading actions have been completed. At this time, the virtual machine allocates memory in the heap memory for the object, and the memory size required by the object can be completely determined during the class loading process. After the memory allocation is completed, the virtual machine starts to initialize the instance variable to a value of 0 (excluding the object header). This step is mainly to ensure that the instance field can be used directly without assignment. Next, the virtual machine starts to make some settings for the object header.

Make it save some class element data information, the object's hash code, the object's GC generation age, etc. At this time, a preliminary object has been created, and only the last step is left, and the <init> method has not been executed.

At this point, the system starts to execute the <init> method to initialize the instance variables according to the programmer's wishes. At this point, the class loading process of an object has completely ended after the object is created.

Now we can try to summarize the whole process as follows:

Load -> connect (verify -> prepare -> parse) -> initialize (execute the <cinit> method) -> allocate object memory in the heap -> set the initial 0 value, and make some necessary settings for the object header -> execute < init>method

->Object created successfully.



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325942022&siteId=291194637