Class loading mechanism (1)

Preface


After studying object-oriented knowledge for a long time, we must be familiar with the concept of "class". When we need an object, we get it through "class", including the reflection we learn, and it is also obtained through class Some information, let’s summarize today, how the JVM loads classes into memory

mind Mapping

Write picture description here

What is class loading?

The JVM loads the class file into the memory, verifies, prepares, parses and initializes the data, and finally it can be formed into a Java type process that can be directly used by the JVM.

The process of class loading

The class loading process goes through several processes, first is loading, then connection (connection is divided into three small steps: verification, preparation, analysis), initialization, and then you can use it, but their order is not exactly in accordance with this A process also has a crossover part. For example, loading and verification may be crossed. The verification of the symbol reference verification occurs during the parsing phase. Let's summarize what these steps have done respectively.

Write picture description here

1. Loading (3 things)

  1. Get the binary byte stream that defines this class through the fully qualified name of a class.
  2. The static storage structure represented by this byte stream is transformed into the runtime data structure of the method area.
  3. A java.lang.Class object representing this class is generated in memory as the access entry for various data of this class in the method area. (Reflective object)

2. Verification (ensure that the loaded class information complies with the JVM specification and there is no security problem)

  • File format verification
  • Metadata verification
  • Bytecode verification
  • Symbol reference verification

Three, prepare

Formally allocate memory for the class variable (static), and set the initial value of the class variable, these memory will be allocated in the method area

public static int value=123; //初始后为 value=0;
//对于static final类型,在准备阶段会被赋予正确的值
public static final value=123;//初始化为 value=123;
//如果是boolean值默认赋值为:false
//如果是对象引用默认赋值为:null

Four, analysis

The process of replacing symbol references in the constant pool with direct references
1. Symbol references: The simple understanding is a string, such as referencing a class, java.util.ArrayList This is a symbol reference, and the object referenced by the string is not necessarily loaded.
2. Direct reference: pointer or address offset. The referenced object must be in memory (already loaded).

Write picture description here

Five, initialization

  1. Method of executing class constructor <clinit>()
  2. This method is generated by the compiler automatically collecting the assignment actions of all class variables in the class and the statement in the static statement block.
  3. Before calling the subclass, ensure that the <clinit> of the parent class is called
  4. The <clinit>() method is correctly locked and synchronized in a multithreaded environment

Note:
<clinit>() is thread-safe. The thread executing <clinit>() needs to acquire the lock before performing the initialization operation, ensuring that only one thread can execute <clinit>() (using this feature can achieve thread-safe laziness Singleton mode).

Demo-changes in memory

Write picture description here

Write picture description here

Memory analysis chart:
Write picture description here

1. The green part on the right is the process of loading Demo1 and Class A
2. Push the stack frame of the main method onto the stack, and then generate an object in the heap, and assign the reference address to a
3. Push the stack frame of A's construction method In the stack, print the static resources in the method area of ​​class A

When will the class be loaded?

Active reference (the initialization of the class will definitely occur)

  1. new an object.
  2. Call static members (except final constants) and static methods of the class.
  3. Call the class through reflection.
  4. The virtual machine starts, and the class where the main method is located is initialized in advance.
  5. Initialize a class, if its parent class is not initialized, initialize the parent class first.

Passive reference (no class initialization will occur)

  1. When accessing a static variable, only the class that actually declares the variable will be initialized. (The child class calls the static variable of the parent class, only the parent class is initialized, and the child class is not initialized).
  2. Defining class references through arrays will not trigger the initialization of this class.
  3. Final variables will not trigger such initialization, because they are stored in the constant pool during the compilation phase.
public class Demo1 {
    
    
    static{
        System.out.println("静态初始化Demo1");
    }
    public static void main(String[] args) {
        //1. age真正的类会被初始化
        System.out.println(B.age);
        //2. 数组不会初始化
        A[] as=new A[10];
        //3.调用类的final常量不会初始化A:被动引用
        System.out.println(A.MAX);
    }
}
class A extends A_Father {
    
    
    public static int age = 24;
    public static final int MAX=100;
    static {
        System.out.println("静态初始化类A");
        age = 25;
    }
    public A() {
        System.out.println("创建A类的对象");
    }
}

class A_Father{
    
    
    static{
        System.out.println("静态初始化A_Father");
    }
}

class B extends A{
    
    
    static{
        System.out.println("静态初始化B");
    }
}

Guess you like

Origin blog.csdn.net/cd18333612683/article/details/79199385