Initialization of JVM class loader class

core-java.jpg

For a static field, only the class that defines the field directly can be initialized. When a class is initializing, all its parent classes must be initialized.

class MParent{
    public static final String mString = "hello jvm";

    static {
        System.out.println("call MParent static block");
    }

}
public class ZiClientA {
    public static void main(String[] args) {
        System.out.println(MParent.mString);
    }
}

Constants are stored in the constant pool of the class where the method calling the constant is located during compilation. From the above code, it can be seen that ZiClientA will save the constant value of mString in MParent to its constant pool instead of referencing the constant mString of MParent class

 public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #4                  // String hello jvm
         5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 14: 0
        line 15: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;
}

java_bean.jpg
3: ldc           #4                  // String hello jvm

In mnemonics, ldc is to pool ZiClientA's own constant pool (see the table of ZiClient.class constant pool below)
How to read this constant table
Understand java bytecode (1)
Understand java bytecode (2)
Understand java bytecode (3)

 #1 = Methodref          #7.#21         // java/lang/Object."<init>":()V
   #2 = Fieldref           #22.#23        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = Class              #24            // com/zidea/jvm/demo/MParent
   #4 = String             #25            // hello jvm
   #5 = Methodref          #26.#27        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #6 = Class              #28            // com/zidea/jvm/demo/ZiClientA
   #7 = Class              #29            // java/lang/Object
   #8 = Utf8               <init>
   #9 = Utf8               ()V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               LocalVariableTable
  #13 = Utf8               this
  #14 = Utf8               Lcom/zidea/jvm/demo/ZiClientA;
  #15 = Utf8               main
  #16 = Utf8               ([Ljava/lang/String;)V
  #17 = Utf8               args
  #18 = Utf8               [Ljava/lang/String;
  #19 = Utf8               SourceFile
  #20 = Utf8               ZiClientA.java
  #21 = NameAndType        #8:#9          // "<init>":()V
  #22 = Class              #30            // java/lang/System
  #23 = NameAndType        #31:#32        // out:Ljava/io/PrintStream;
  #24 = Utf8               com/zidea/jvm/demo/MParent
  #25 = Utf8               hello jvm
  #26 = Class              #33            // java/io/PrintStream
  #27 = NameAndType        #34:#35        // println:(Ljava/lang/String;)V
  #28 = Utf8               com/zidea/jvm/demo/ZiClientA
  #29 = Utf8               java/lang/Object
  #30 = Utf8               java/lang/System
  #31 = Utf8               out
  #32 = Utf8               Ljava/io/PrintStream;
  #33 = Utf8               java/io/PrintStream
  #34 = Utf8               println
  #35 = Utf8               (Ljava/lang/String;)V

Mnemonic symbol

  • ldc means pushing constant values of type int, float or String to the top of the stack
  • bipush means to push the constant value of a single byte (- 128 ~ 127) to the top of the stack
  • sipush means to push a short constant value to the top of the stack
  • Iconst? 1 means to push the int type (iconst? M1 - iconst? 5) to the top of the stack

Static variables

public static final short P_SHORT = 1000;
 stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: sipush        1000
         6: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V
         9: return
public static final int P_MINUS_COUTER = -1;
Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: iconst_m1
         4: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V
         7: return

Look at the source code in ICONST. From the source code, you can see that ICONST_1loads several special shaped values to the top of the stack, and ((I > = - 1) & & (I < = 5)) processes these special characters.

 public ICONST(final int i) {
        super(com.sun.org.apache.bcel.internal.Const.ICONST_0, (short) 1);
        if ((i >= -1) && (i <= 5)) {
            super.setOpcode((short) (com.sun.org.apache.bcel.internal.Const.ICONST_0 + i)); // Even works for i == -1
        } else {
            throw new ClassGenException("ICONST can be used only for value between -1 and 5: " + i);
        }
        value = i;
    }
i263315.jpg

Tags: Java jvm Apache

Posted on Sun, 01 Dec 2019 18:34:14 -0500 by johnbrayn