In-depth understanding of the Java class loading mechanism of the Java virtual machine, and a detailed explanation of the Java class instantiation process.

Table of contents

Java class loading mechanism

class loading process

Loading

Linking

Initialization

Using

Unloading


introduction

  1. When to start the first phase of the class loading process: loading?
    1. Answer: There is no mandatory constraint in the Java virtual machine specification, which can be freely grasped by the specific implementation of the virtual machine. But for the initialization phase, the virtual machine strictly stipulates that there are only 5 situations in which the class must be "initialized" immediately , and the processes of loading, verification, and preparation naturally need to be carried out before this.
  2. What is the detailed implementation of the instantiation process of the class? ? ?
  3. When and how the virtual machine loads the Class file, and what happens to the Class file information when it enters the virtual machine?
  4. What are symbolic references and direct references? ? ?
  5. What is initialization? ?
  6. What is the difference between interface and class in initialization? ?
  7. What is the difference between the class constructor <clinit>() method and the instance constructor <init>() method? ?

The focus of this article

  • Detailed explanation of the instance process of a class

  • Class initialization conditions

For more details, please read this article


  • class life cycle

1. Loading

  1. loaded content

    1. Get the binary byte stream that defines this class through the fully qualified name of a class, what are the specifics?

      1. Read from a zip package, which eventually becomes the basis for JAR, EAR, WAR formats

      2. Obtained from the network, typical application Applet

      3. Runtime calculation generation, dynamic proxy technology

      4. Generated from other files, typical scenario Jsp application, the corresponding class is generated from the jsp file

      5. Reading from the database, there are fewer scenarios, such as: Some middleware servers (SAP Netweaver) can choose to install the program into the database to complete the distribution of the program code in the cluster

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


Two connections (Linking)

  1. Verification

    1. What is included in the file format validation?
      1. Does it start with the magic number CAFFBABE
      2. The major and minor version numbers are within the processing range of the virtual machine
      3. Whether there is an unsupported constant type in the constant in the constant pool
      4. Whether the various index values ​​pointing to constants point to non-existent constants or constants that do not conform to the type
      5. Does the CONSTANT_Utf8_info type constant have data that does not conform to UTF8 encoding, etc.
    2. What is included in the metadata validation?
      1. Does this class have a parent
      2. Whether the parent class of this class inherits a class that does not allow inheritance (final class)
      3. If the class is not an abstract class, whether it implements all the methods required to be implemented in the parent class or in the abstract interface
      4. Whether the fields in the class conflict with the parent class, such as: Overriding the final field of the parent class does not conform to the rule of method overloading
    3. What is the content of bytecode verification?
      1. Ensure that jump instructions do not jump to bytecode instructions outside the method body
      2. Ensures that type conversions in method bodies are valid
      3. Ensure that the data type in the operand stack and the instruction code sequence can work together at any time
    4. Symbolic reference verification
      1. Purpose: To ensure that the parsing action can be executed normally
      2. What are the contents?
        1. Whether the fully qualified name described by the string in the symbol reference can find the corresponding class
        2. Whether the accessibility of classes, fields, and methods in symbolic references can be accessed by the current class
        3. A field description conforming to the method and the simple name and field exist in the specified class
  2. Prepare

    1. The preparation stage is the stage of formally allocating memory for the class variable and setting the initial value of the class variable (static modified variable). The initial value is usually the "zero value" of the data type
    2. zero value
      1. The zero value of the integer is: 0
      2. The zero value of the boolean n type is: false
      3. The zero value of a reference type is: null
    3. Suppose a class variable is defined as: public static int value=1234; the value of the variable value after the preparation phase is not 1234, but 0. The value of value will be 1234 only after the initialization phase.
  3. Resolution

The resolution process is the process in which the virtual machine replaces symbolic references in the constant pool with direct references.

  1.  
    1. Preliminary knowledge
      1. What are symbolic references and direct references? ? ?
      2. Symbolic references (the concept of compilation principles) include the following three types of constants
        1. fully qualified names of classes and interfaces
        2. Field names and descriptors
        3. method name and descriptor
      3. Definitions for direct quotes
        1. A pointer directly to the target
        2. relative offset
        3. A handle to an indirect location target
    2. What does the analysis include?
      1. class or interface
      2. field
      3. class method
      4. interface method
      5. method type
      6. method handle
      7. call site qualifier

 

Three initialization (Initialzation)

  1. Preliminary knowledge
    1. What is initialization?
      1. That is, the process of executing the class constructor <clinit>() method. The last step of the class loading process, the previous process is completely dominated and controlled by the virtual machine (except through the participation of the custom loader), and the initialization phase really starts to execute the Java code (or bytecode) defined in the class.

    2. What is the process of executing the class constructor <clinit>() method?

      1. The <clinit>() method is generated by the combination of the assignment actions of all class variables in the class automatically collected by the compiler and the statements in the static statement block (Static{} block). The order of collection by the compiler is determined by the statement in the source file Determined by the order of appearance, the static statement can only access the variables defined before the static statement block, and the variables defined after it can be assigned in the static statement block, but cannot be accessed.
      2. The <clinit>() method is not necessary for classes and interfaces, if there are no static modified methods, code blocks, or variables. The compiler may not generate the <clinit> method for it
    3. What is the difference between interface and class in initialization?
      1. It will only be initialized when the parent interface is actually used, such as: referencing the constants defined in the parent interface
    4. What is the difference between the class constructor <clinit>() method and the instance constructor <init>() method?
      1. Without explicitly calling the parent class constructor, the virtual machine guarantees that the <clinit> method of the parent class has been executed before the <clinit>() method of the subclass is executed.
      2. Therefore, it means that the first implementation of the <clinit>() method in the virtual machine must be java.lang.Object, and the static statement block defined in the parent class precedes the variable assignment operation of the subclass
  2. initialization condition
    1. When encountering the four bytecode instructions of new, getstatic, putstatic, and invokestatic.
    2.  When using the java.lang.reflect package to make a reflective call to a class, if the class has not been initialized, it needs to be triggered to be initialized first
    3. When initializing a class, if its parent class has not been initialized, you need to trigger its parent class to initialize first
    4. When the virtual machine starts, the user needs to specify a main class (including the main method) to be executed, and the virtual machine first initializes the main class,
    5. If the final parsing result of the java.lang.invoke.MethodHandle instance is the handle of REF_getstatic, the handle of REF_putstatic, or the method handle of REF_invokestatic, and the class corresponding to the method handle has not been initialized, its initialization needs to be triggered first.

 

  1. The situation that does not trigger initialization, passive reference, three examples are given later.

     

    1. The subclass refers to the static field of the parent class. For the static field, only the class that directly defines this field will be initialized.
    2. References to constant fields of other classes will not trigger such initialization, compilation phase, and constant propagation optimization.
    3. References to classes through array definitions do not trigger such initialization

Example code demo


Demonstration 1: The instance creation process of a class:  

Preliminary knowledge

  • The meaning of initialization:

Execute the class constructor <clinit>() method, which is the process of assigning values ​​to class variables + executing the static statement block static{}.

  • Why is the constructor of the parent class called first when instantiating an object of the subclass?

Answer: After the subclass inherits the parent class, it obtains the properties and methods of the parent class. These properties and methods must be initialized before use, so the constructor of the parent class must be called to initialize

  • How to call the constructor of the parent class?

In the first line of the subclass constructor, super(); will be called implicitly, that is, to call the parent class constructor. If there is no constructor with empty parameters defined in the parent class, it must be the first line of the subclass constructor. Call super(parameter); to call the constructor in the parent class. If the first line of the constructor in the subclass writes this();, the implicit super(); will disappear, because super( ) and this() can only be defined on the first line of the constructor


class  C{
	C() {
        System.out.println("正执行SuperClass类的构造方法对成员变量初始化,为其成员变量C分配内存空间");
    }

}

class SuperClass {
    C c = new C();
	static{
	System.out.println("SuperClass类 正在初始化");
}
	
	SuperClass() {
        this("正在调用SuperClass的有参构造方法");
        System.out.println("正在执行SuperClass的无参构造方法");
    }
 
	SuperClass(String s) {
        System.out.println(s);
    }
}

public class SubClass extends SuperClass{
	static{
	System.out.println("SubClass类 正在初始化");
}
	SubClass() {
        /*在子类构造方法的第一句,隐式的调用父类的构造方法;*/
        System.out.println("正在执行子类SubClass的构造方法");
    }
	 public static void main(String[] args) {
	        new SubClass();
	    }
}

 

 

class instance procedure

  1. When the virtual machine starts, the user needs to specify a main class (including the main method) to be executed, and the virtual machine first initializes the main class. That is, the SubClass class
  2. When initializing a class, if its parent class has not been initialized, you need to trigger its parent class to initialize first. That is, the parent class SuperClass of the SubClass class needs to be initialized first.
  3. Since the parent class does not explicitly inherit a class, the virtual machine defaults to inheriting the ancestor class of all classes, namely the java.lang.Object class. That is, the Object class needs to be initialized. All in all, the first implementation of the <clinit>() method in the virtual machine must be java.lang.Object, and the static statement blocks defined in the parent class and the variable assignment operations of the class must precede the subclass.
  4. Initialize the parent class SuperClass of SubClass class, output " SuperClass class is initializing "
  5. Initialize the subclass SubClasst of the parent class SuperClass, output " SubClass class is initializing "
  6. When the static statement block of the SubClasst class is executed, the new keyword is encountered and the construction method of the subclass is called. The first line of the subclass constructor will implicitly call super();, that is, the construction method of the parent class is called first.
  7. Call the construction method of the parent class, allocate memory for the member variables in the class, and execute the statements in the construction method.
    1. That is, first output " The construction method of the SuperClass class is being executed to initialize the member variables, and allocate memory space for its member variable C, and the assignment of member variables precedes the statement in the construction method "
    2. Then output " The statement in the no-argument constructor of SuperClass is being executed "
  8. Call the construction method of the subclass, allocate memory for the member variables in the class, and execute the statements in the construction method. Output " The statement in the no-argument constructor of the subclass SubClass is being executed "

 

  • Passive reference demonstrates that a subclass refers to a static field of the parent class. For a static field, only the class that directly defines this field will be initialized.

package negtive_reference;
/*
 * 被动使用字段演示一
      通过子类引用父类的静态字段,不会导致子类初始化
*/

public class SuperClass {
	static{
	System.out.println("SuperClass Init");
}
	public static int value=123;

}

package negtive_reference;

public class SubClass extends SuperClass{
	static{
		System.out.println("SubClass Init");
	}
}

package negtive_reference;

public class NotInitialization {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(SubClass.value);
	}

}

Output content:

 


  • Passive reference demonstration 2 refers to constant fields of other classes, which will not trigger such initialization, compilation phase, and constant propagation optimization.

 

package negtive_reference;
	/*常量在编译阶段会调入类的常量池,
	 *本质上并没有直接引用到定义常量的表,
	 *因此不会触发定义常量的类的初始化*/
public class ConstantClass {
	static{
	System.out.println("ConstantClass Init");
}
	public static final String HELLOWOELD="hello world";
}
package negtive_reference;

public class NotInitialization {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		/*System.out.println(SubClass.value);*/
		/*SuperClass[] sca= new SuperClass[10];*/
		System.out.println(ConstantClass.HELLOWOELD);
	}

}

 output: no output

 

  • Passive reference demonstration 3 refers to the class through the array definition, and will not trigger such initialization

package negtive_reference;
/*
 * 被动使用字段演示一
      通过数组来引用类,不会触发此类的初始化
*/

public class SuperClass {
	static{
	System.out.println("SuperClass Init");
}
	public static int value=123;

}



package negtive_reference;

public class NotInitialization {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SuperClass[] sca= new SuperClass[10];
	}

}

output: no output

Summary: There are three stages in which variables can be assigned

  • In the preparation stage, set the initial value for the class variable, that is, give it the "zero value" of the corresponding data type.
  • In the initialization phase, class variables are assigned the values ​​declared by the user in the program. In the previous article, the value was assigned to 1234
  • When creating an instance of a class, when executing its construction method init(), if the member variable declaration does not specify an initial value, and the construction method used does not initialize the member variable, the member variable will be assigned the "zero value" of its corresponding data type. value".

Note: The first two stages are for class variables, that is, variables modified by the static keyword, and the first two stages will not set initial values ​​for instance variables.

If you think this article is good, if it is helpful to you, you can like it!



 

Guess you like

Origin blog.csdn.net/qq_38537709/article/details/88750605
Recommended