[Initialization] step analysis in the class loading mechanism

foreword

We know that the system has these steps to load .class files: three stages: loading , connection , and initialization .

In the loading phase, the binary byte stream of the corresponding file will be obtained through the full class name, and then a Class object will be generated through the native method. This step is mainly completed by the class loader . That is to say, the Class object is generated in the first step.

The connection phase is divided into three steps : verification , preparation , and analysis . The JVM will assign initial values ​​to all static variables of the class during the preparation phase .

In the final initialization<clinit> () stage, the JVM will execute the method generated at compile time (when the javac command generates . The previous preparation stage does not initialize static variables, but only assigns initial values ​​to static variables, such as the int type is assigned a value of 0, and the specific value needs to be assigned in the initialization stage.

But static constants, that is, variables modified by final, will be initialized in the preparation phase.

Initialization step analysis

According to the above conclusions, we know that the initialization phase is actually the period of initializing class static variables.

We know 类名.classand Class.forName("类名")can get the Class object of the corresponding class, but the former will not be initialized, while the latter will be initialized. Now look at an example to appreciate the difference:

import org.junit.Test;

public class MyTest {
    
    

    @Test
    public void test1(){
    
    
        System.out.println(Apple.class);
    }
    @Test
    public void test2() throws ClassNotFoundException {
    
    
        System.out.println(Class.forName("Apple"));
    }
}

class Apple {
    
    
    static {
    
    
        System.out.println("static init");
    }
}

The output of test1 is as follows:

The output of test2 is as follows:

It can be found 类名.classthat since the initialization step will not be performed, there is indeed no execution <cinit>()method, and the static code block is taken.

Class.forName(String name, boolean initialize, ClassLoader loader) method parameter analysis

We know that Class.forName()the method actually has an overloaded method that can pass in a Boolean value and a ClassLoader. In fact, this Boolean value tells the JVM whether to perform the initialization step .

Add test3 to the class just now:

@Test
    public void test3() throws ClassNotFoundException {
    
    
        System.out.println(Class.forName("Apple", false, Apple.class.getClassLoader()));
    }

Execute this method, the output is as follows:

Note that because false is set, the forName method does not initialize the Apple class this time.

Initialization of the Main method

In fact, if it is main()the class where the method is located, there are some small details worth noting.

Suppose you have the following code:

public class MyTest {
    
    
    public static void main(String[] args) throws ClassNotFoundException {
    
    
    }
    public Apple apple(){
    
    
        return new Apple();
    }
}

Even if there is no code in the running main()method, if we delete the Apple.class file in the path before running, the following error will be reported:

It can be noticed that even if main()it does not run any code, it will load all the classes referenced in its class MyTest, here is the Apple class. And the loading here also does not perform initialization steps .

Modify the above code as follows:

public class MyTest {
    
    
    public static void main(String[] args) throws ClassNotFoundException {
    
    
    	new Banana();
    }
}
class Banana{
    
    
    public Apple apple(){
    
    
        return new Apple();
    }
}

Delete the Apple.class file in the path before running, and find that no error will be reported, and the program will exit normally.

From this, it can be concluded that when the JVM runs main()the class, it will load all types of Class objects referenced by the class into memory.

Guess you like

Origin blog.csdn.net/weixin_55658418/article/details/130036224