Loaders such as the four major modules of JVM

JVM class loading and class loader
class loading

The life cycle of a class is composed of 7 stages, as shown in the figure
 

First, the loading stage of the
class 1. Obtain the class file that stores the class through the full naming of the class ( acquisition method )

2. Parse into runtime data, that is, instanceKlass instance, stored in the method area

3. Generate the class object of this class in the heap area, namely the instanceMirrorKlass instance

When to load

-When actively using

1、new、getstatic、putstatic、invokestatic

2. Reflection

3. Initializing a subclass of a class will load its parent class

4. Startup class (the class where the main function is located)

5. When using jdk1.7 dynamic language support, if the final analysis result of a java.lang.invoke.MethodHandle instance has REF_getstatic, REF_putstatic, and REF_invokeStatic method handles, and the class corresponding to this method handle has not been initialized, you need to first Trigger its initialization

-Pre-loading: wrapper class, String, Thread

Obtaining methods such as

1. Read from the compressed package, such as jar, war

2. Obtain from the Internet, such as Web Applet

3. Dynamic generation, such as dynamic proxy, CGLIB

4. Generated by other files, such as JSP

5. Read from the database

6. Read from encrypted files

Verification phase

1. File format verification

2. Metadata verification

3. Bytecode verification

4. Symbol reference verification

preparation stage

Allocate memory for static variables and assign initial values: for example, int = 0; long = 0L;

When the instance variable is assigned when the object is created, there is no saying that the initial value is assigned

If the variable is modified by final, then the constantValue attribute will be added to the attribute when compiling, and the assignment will be completed directly in the preparation phase (compiled)

    public static int a = 20;
    public static final int b = 30;
    public static void main(String[] args) {
        //不运行直接编译
    }

Parsing stage

Popular point is that indirect reference -> direct reference

Indirect reference: a reference to the runtime constant pool

Direct reference: memory address

Still use this Test object, let's take a look at the constant pool information after compilation and running

    public static int a = 20;
    public static final int b = 30;
    public static void main(String[] args) {
        for (;;);//运行中
    }

1. After compiling, switch to the classes directory and use javap -verbose or jclasslib

For example, mine is D:\spring-boot\boot\target\classes>javap -verbose com.waf.boot.wk.Test The result obtained is a reference to the constant pool
javap -verbose

D:\spring-boot\boot\target\classes>javap -verbose com.waf.boot.wk.Test
Classfile /D:/spring-boot/boot/target/classes/com/waf/boot/wk/Test.class
  Last modified 2021-3-24; size 566 bytes
  MD5 checksum d7655afea6f7cf4d8b5ab6005cd334ab
  Compiled from "Test.java"
public class com.waf.boot.wk.Test
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#26         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#27         // com/waf/boot/wk/Test.a:I
   #3 = Class              #28            // com/waf/boot/wk/Test
   #4 = Class              #29            // java/lang/Object
   #5 = Utf8               a
   #6 = Utf8               I
   #7 = Utf8               b
   #8 = Utf8               ConstantValue
   #9 = Integer            30
  #10 = Utf8               <init>
  #11 = Utf8               ()V
  #12 = Utf8               Code
  #13 = Utf8               LineNumberTable
  #14 = Utf8               LocalVariableTable
  #15 = Utf8               this
  #16 = Utf8               Lcom/waf/boot/wk/Test;
  #17 = Utf8               main
  #18 = Utf8               ([Ljava/lang/String;)V
  #19 = Utf8               args
  #20 = Utf8               [Ljava/lang/String;
  #21 = Utf8               StackMapTable
  #22 = Utf8               MethodParameters
  #23 = Utf8               <clinit>
  #24 = Utf8               SourceFile
  #25 = Utf8               Test.java
  #26 = NameAndType        #10:#11        // "<init>":()V
  #27 = NameAndType        #5:#6          // a:I
  #28 = Utf8               com/waf/boot/wk/Test
  #29 = Utf8               java/lang/Object
{
  public static int a;
    descriptor: I
    flags: ACC_PUBLIC, ACC_STATIC

  public static final int b;
    descriptor: I
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    ConstantValue: int 30

  public com.waf.boot.wk.Test();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/waf/boot/wk/Test;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=0, locals=1, args_size=1
         0: goto          0
      LineNumberTable:
        line 8: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       3     0  args   [Ljava/lang/String;
      StackMapTable: number_of_entries = 1
        frame_type = 0 /* same */
    MethodParameters:
      Name                           Flags
      args

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: bipush        20
         2: putstatic     #2                  // Field a:I
         5: return
      LineNumberTable:
        line 5: 0
}
SourceFile: "Test.java"

Mainly look at Constant pool:

#3 = Class #28 // com/
waf /boot/wk/Test jclasslib gets a reference to the constant pool

2. After running, the real memory address can be seen in HSDB through the process number

 Initialization phase

Execute the static code block to complete the assignment of static variables

Static fields, static code segments, and clinit methods are generated at the bytecode level

The order of the statements in the method is related to the order in which the code is written

We can look at a few examples of static

public class Test_1 {
    public static void main(String[] args) {
        System.out.println(Test_1_B.str);
    }
}

class Test_1_A{
    static {
        System.out.println("a static");
    }
}

class Test_1_B extends Test_1_A{
    public static String str = "a str";
    static {
        System.out.println("b static");
    }
}
//output
a static
b static
a str

 

public class Test_1 {
    public static void main(String[] args) {
        System.out.println(Test_1_B.str);
    }
}

class Test_1_A{
    public static String str = "a str";
    static {
        System.out.println("a static");
    }
}

class Test_1_B extends Test_1_A{
    static {
        System.out.println("b static");
    }
}
//output
a static
a str

 

How is this static field stored in klass-look at Test_1_A & Test_1_B in the second example through the HSDB tool

Stored in instanceMirrorKlass (Oop) and Test_1_B has no str attribute (only the inheritance relationship of Java syntax exists). How did the bottom layer find it (I don’t understand...)

public class Test_1 {
    public static void main(String[] args) {
        System.out.println(new Test_1_B().str);
    }
}

class Test_1_A{
    public  String str = "a str";
    static {
        System.out.println("a static");
    }
}

class Test_1_B extends Test_1_A{
    static {
        System.out.println("b static");
    }
}
//output
a static
b static
a str

The way JVM reads static properties (example two) (how did you find it at the bottom (didn't understand...))

str is a static attribute of the class Test_1_A, you can see that it will not be stored in the mirror class of the subclass Test_1_B

As you can guess, there are two ways to access the static fields of the parent class Test_1_A through the subclass Test_1_B:

1. First go to the mirror class of Test_1_B to get it, if there is a direct return; if not, the request will be thrown up along the inheritance chain. Obviously, the performance of this algorithm increases with the death of the inheritance chain, and the algorithm complexity is O(n)

2. With the aid of another data structure, the KV format is used for storage, and the query performance is O(1)

Hotspot is the second method used. With the help of another data structure ConstantPoolCache, there is an attribute _cache in the constant pool class ConstantPool that points to this structure. Each piece of data corresponds to a class ConstantPoolCacheEntry.

Where is ConstantPoolCacheEntry? Behind the ConstantPoolCache object, look at the code C++

\openjdk\hotspot\src\share\vm\oops\cpCache.hpp

ConstantPoolCacheEntry* base() const           { 
  return (ConstantPoolCacheEntry*)((address)this + in_bytes(base_offset()));
}

This formula means the address of the ConstantPoolCache object plus the memory size of the ConstantPoolCache object

ConstantPoolCache

The constant pool cache is a runtime data structure reserved for the constant pool. Interpreter runtime information that stores all field access and call bytecodes. The cache is created and initialized before the class is actively used. Each cache item is filled when it is parsed

How to read

\openjdk\hotspot\src\share\vm\interpreter\bytecodeInterpreter.cpp

CASE(_getstatic):
        {
          u2 index;
          ConstantPoolCacheEntry * cache;
          index = Bytes::get_native_u2(pc+1);

          // QQQ Need to make this as inlined as possible. Probably need to
          // split all the bytecode cases out so c++ compiler has a chance
          // for constant prop to fold everything possible away.

          cache = cp->entry_at(index);
          if (!cache->is_resolved((Bytecodes::Code)opcode)) {
            CALL_VM(InterpreterRuntime::resolve_get_put(THREAD, (Bytecodes::Code)opcode),
                    handle_exception);
            cache = cp->entry_at(index);
          }
……

As can be seen from the code, it is directly to get ConstantPoolCacheEntry

 

 

 

Class loader

 

 

 

Guess you like

Origin blog.csdn.net/qq_38108719/article/details/115167676