A brief explanation of the class loading process (timing)

Directory:
java virtual machine summary

  1. Class file structure analysis
    1). The constant item structure in the class file constant pool
    2). A collection of commonly used attribute tables
  2. Class loading process <<== Current position
    1). Principle and implementation of class loader
  3. Virtual machine structure analysis
    1) .jdk 1.7 and 1.8 version of the method area structure changes
    2). Simple distinction between constant pools
  4. Object structure analysis
    1). Detailed explanation of compressed pointers
  5. gc garbage collection
  6. Object positioning method

Off-topic link in this article: class loader and its implementation.
Class loading, worthy of the name, is to load the content of your class file into the jvm. The process is divided into three parts. The loading link is initialized. First, understand when class loading occurs.

1. Timing of class loading (class initialization) (when does class loading occur)

—When your class is instantiated, an instance of this object is created new Test();
—When you access or modify the static variable in the class Test.a=4; —When
you call this When the static method of the class is Test.getA();
-when you use reflection Class.forName()
- when the subclass of this class is initialized-
the startup class marked when the JVM is started, that is, the file name and the class name are the same that class
also need to pay attention to several points of
access final modified constant and does not initialize
static variables subclasses access to the parent class, initialize the parent class, subclass does not initialize

2. Class loading process

Insert picture description here

  1. Loading
    This loading is the first step of class loading. Wasn't there only one class file? Now the process of loading is to load this class file into the jvm in a binary stream using the class loader , and generate a Class object (that is, we call Test.class is java.lang.Class), stored in the heap, detailed class loader and its implementation


  2. Why is a link (connection) called a link? In fact, it is to convert the symbolic reference into a direct reference . In the vernacular, don’t you use the **_index symbol to point to a constant item in your calss file? This is a symbolic reference. Java does not know the actual address referenced. It may be just a utf8 string, it is not a memory address, direct reference means that after allocation, your stack or method area will have an actual address leading to the stored address, which is direct reference to
    convert symbol reference into direct reference The link also does these things. The
    link is divided into three steps here.

    1. ) Verify

      Official words:

      Verification is the first step in the connection phase. The purpose of this phase is to ensure that the information contained in the byte stream of the Class file meets the requirements of the current virtual machine and does not endanger the virtual machine's own security.

      It is divided into

      1. File format verification Is the
        magic number coffee baby? Can our virtual machine handle your version number? Is there any type of constant pool that cannot be processed, etc... Details Baidu.

      2. Metadata Verification
        Whether this class inherits a class that is not allowed to be inherited (final), and if it can be instantiated, does it cover all the abstract methods of the parent class? . and many more

      3. Bytecode verification Make
        sure the program semantics are legal and logical

      4. Symbol reference verification
        , whether the fully qualified name found in the symbol reference has a corresponding class, etc.

      In a word: check whether there is a problem with this class , do not explain in detail, if there is a need, Baidu

    2. ) Prepare

      The preparation stage is to formally allocate memory for the class variable and set the initial value of the class variable. For example, you define a
      static int a = 3;
      then at this stage, a storage space of a will be reviewed and assigned the default value of 0, the value of a at this time 0, of
      course, that is to say that the static variable has been created at this time, but has not been assigned (only the initial value), and then uniformly assigned during initialization .
      Note: If the variable is static , then this value will be here Is assigned, and then stored as a constant in the runtime constant pool

    3. ) Analysis The
      parsing phase is the process of replacing the symbol references in the constant pool with direct references by the virtual machine . The main process of our connection
      is that the original class and class information have been stored in memory (done during loading), but at this time your Test.b cannot successfully access the b variable. At this time, your a is still a symbolic reference that cannot point to the corresponding address in the correct Class, so this step is to point all your references to the actual address, that is, replace the symbolic reference with a direct reference. The
      detailed process Very complicated

      1. Class or interface resolution
      2. Field parsing
      3. Class method analysis
      4. Interface method analysis

    To understand the specific steps, you can Baidu

  3. Initialization
    Initialization is also the last step of class loading. Remember, in the vernacular, it is to assign initial values ​​to the variables you have applied for. For example, you have applied for variable space during the preparation process of the connection process, but there is no assignment at this time, so in the Here will be unified assignment, he will default all the assignment statements you write according to the static variable assignment and the assignment of the static code block that you write, extract them in order and execute them in order, such as

class Test{
    
    
	static int a = 4;
	static{
    
    
		a=9;
	}
}

In the preparation phase here, the variable space of a has been applied, but the default value is 0. Here, the variable assignment operation a=4, the operation a=9 in the static code block is taken off and executed in turn, that is, a is assigned to 4, Then assign the value to 9, and the final value is 9. In fact, the function of the static code block here is just to initialize the static variable, just like our constructor is to initialize the variable, let’s
look at an example

class Test{
    
    
	static int a = 1;
	static{
    
    
		int a = 3;
	}
	public static void main(String []ages){
    
    
		System.out.println(a);
	}
	输出1
}

…Don’t be confused, the int a in this static code block is just a local variable.

lass Test{
    
    
	
	static{
    
    
		a = 3;
		System.out.println(a);
	}
	static int a = 1;
	public static void main(String []ages){
    
    
		
	}
	非法向前引用

At this time, a can be assigned, that is, a=3 will not report an error, because our a has been applied for storage space, and the output statement will report an illegal forward reference exception. Just pay attention, and only access to the static statement block Variables defined before the static statement block, variables defined after it, can be assigned to the previous static statement block, but cannot be accessed! ! !

In order to deepen the initialization of variables, let's look at an example. See what is output

class Test{
    
    
	private static Test test = new Test();
    public static int a;
    public static int b=0;
     
    private Test(){
    
    
        a++;
        b++;
    }
    public static Test getTest(){
    
    
        return test;
    }
    public static void main(String []ages){
    
    
   		System.out.println(Test.getTest().a);
		System.out.println(Test.getTest().b);
	}
}

Insert picture description here
Of course, this is a singleton mode. Let’s analyze it.
The preparation process in the connection step: Assign initial value null, 0, 0 to test, a, b.
Initialization process: Extract assignment statements and execute them in order. Pay attention to this When I found the new Test() statement, at this time a is 0 and b is 0! ! , And then new, execute the construction code block (not here) and the construction method, increase a and b, at this time a and b are both 1, and then continue to extract, int a statement is skipped without assignment statement, int b= 0 The b=0 of this statement is taken out, and then there is no static code block, the end, all of these will be installed in the clinit method (if you are interested in understanding Baidu), they will be executed in a unified way, that is, at this time The statement in clinit is test = new Test(); b=0;
As a result, b is re-assigned to 0. Note that b is static at this time, and there is only one class in the whole class, so it will affect the object that was previously new, so the output b It's 0, so let's try another order?

class Test{
    
    
   
   public static int a;
   public static int b=0;
   private static Test test = new Test();
   private Test(){
    
    
       a++;
       b++;
   }
   public static Test getTest(){
    
    
       return test;
   }
   public static void main(String []ages){
    
    
  		System.out.println(Test.getTest().a);
   	System.out.println(Test.getTest().b);
   }
}

The output of this sentence is normal.
Insert picture description here
Please be on the side of the analysis. I will not analyze it here.

Summary: Class loading process:
Loading process: In a word, transfer the class file into bytes, then convert it into a class object, and put it into memory.
Connection process: In a word, convert symbolic reference to direct reference
initialization Process: In a word, the static initialization code is executed sequentially
! ! Remember that class loading refers to the three parts of loading, connection, and initialization. The trigger conditions are pointed out at the beginning. We can also load separately (implement a class loader to load by ourselves). We cannot simulate the connection process, which involves memory and initialization. The process is the same, but you should know: the connection process depends on loading, and the initialization process depends on connection and loading. If you often don’t know about class loading and class initialization, you should understand it here. That is to say, class loading can also be written as class initialization to some extent, because After the initialization is triggered, the first two steps will be executed immediately if the first two steps are not executed

If there is any error in this article, please point it out immediately, and the blogger will correct it immediately

Guess you like

Origin blog.csdn.net/lioncatch/article/details/106032324