jvm operand stack

Runtime data Area
Insert picture description here

What is the operand stack?

  • Like the local variable table, it is an array with word length as the unit. However, the local variable table uses an index, and the operand stack is accessed by popping/pushing the stack. The operand stack can be understood as a temporary data storage area used for calculation in the java virtual machine stack.
  • The stored data is consistent with the local variable table and contains int, long, float, double, reference, returnType. The byte, short, and char in the operand stack will be converted to int before being pushed onto the stack (bipush).
  • For data operations, most instructions are popped up on the operand stack, and then the result is pushed onto the stack.
  • The java virtual machine stack is the space for method call and execution, and each method will be encapsulated into a stack frame and pressed into the occupied. The operand stack inside is used to perform operations, and only the currently executing method in the current thread will call instructions in the operand stack (it can be seen that the instructions of the java virtual machine stack are mainly taken from the operand stack).
  • The int type is in the range of -15 , -128 127, -32768 32767, -2147483648 2147483647, and the corresponding instructions are iconst, bipush, sipush, and ldc (this is directly stored in the constant pool)
public class Hello {
    public static void main(String[] args) {
        Hello hello = new Hello();
        int testVal = hello.test();
    }
 
    public int test() {
        //int类型
        int a = 5 + 10;      //验证直接相加在编译阶段已合并完结果
        int b = a + 3;        //探究变量与常量的相加过程
        b = b + 6;             //验证int不在-1~5,在-128~127范围的指令是bipush
        b = b + 128;         //验证int不在-128~127,在-32768~32767范围的指令是sipush
        b = b + 32768;     //验证int不在-32768~32767,在-2147483648~2147483647范围的指令是ldc(ldc:从常量池取并压栈,所以这个范围的int是存在常量池)
        //short                  //验证byte、short、char在操作数栈压栈前均会转为int
        short a_s = 5 + 10;
        short b_s = (short)(a_s + 3);
        //float类型            //以下验证float、double、String均是从常量池中取出(均使用了ldc、ldc_w、ldc2_w其中一个)
        float a_f = 5.00F + 10.00F;
        float b_f = a_f + 3.00F;
        //double类型
        double a_d = 5.00D + 10.00D;
        double b_d = a_d + 3.00D;
        //String类型
        String a_str = "a" + "b";
        String b_str = a_str + "c";
        return b;
    }
}

First, this will be stored in the Code property of the method, javac Hello.java is compiled, and then javap -verbose Hello.class is decompiled and analyzed. The test() method is as follows:

    Code:
      stack=4, locals=13, args_size=1
         0: bipush        15 //1 15压入操作数的栈顶(编译过程中5+10合并成15,并且由于15在-128-127范围,即用bipush)  压栈
         2: istore_1           //2  从栈顶弹出并压入局部变量表访问索引为1的Slot                                                                    弹栈入局部变量表
         3: iload_1            //3  将局部变量表中访问索引为1的Slot重新压入栈顶                                                                    局部变量表入栈
         4: iconst_3          //4  数值3压入操作数的栈顶(范围-1~5,即用指令iconst)                                                              压栈
         5: iadd                //5  将栈顶的前两个弹出并进行加法运算后将结果重新压入栈顶                                                     前两弹栈相加
         6: istore_2          //6   从栈顶弹出并压入局部变量表访问索引为2的Slot                                                                    弹栈入局部变量表
         7: iload_2            //7  将局部变量表中访问索引为2的Slot重新压入栈顶                                                                    局部变量表入栈
         8: bipush        6  //8  6压入操作数的栈顶(在-128-127范围,用bipush指令) 
        10: iadd
        11: istore_2
        12: iload_2
        13: sipush     128//9  128压入操作数的栈顶(在-32768~32767范围,用sipush指令) 
        16: iadd
        17: istore_2
        18: iload_2
        19: ldc           #5  // int 32768  //10  128压入操作数的栈顶(在-2147483648~2147483647范围,用ldc指令) 
        21: iadd
        22: istore_2
        23: bipush        15 //11  验证了short、byte、char压栈前都会转为int
        25: istore_3
        26: iload_3
        27: iconst_3
        28: iadd
        29: i2s
        30: istore        4
        32: ldc           #6   // float 15.0f //12  以下验证float、double、String均是从常量池中取出(均使用了ldc、ldc_w、ldc2_w其中一个)
        34: fstore        5
        36: fload         5
        38: ldc           #7                  // float 3.0f
        40: fadd
        41: fstore        6
        43: ldc2_w        #8                  // double 15.0d
        46: dstore        7
        48: dload         7
        50: ldc2_w        #10                 // double 3.0d
        53: dadd
        54: dstore        9
        56: ldc           #12                 // String ab
        58: astore        11
        60: new           #13                 // class java/lang/StringBuilder
        63: dup
        64: invokespecial #14                 // Method java/lang/StringBuilder."<init>":()V
        67: aload         11
        69: invokevirtual #15                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        72: ldc           #16                 // String c
        74: invokevirtual #15                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        77: invokevirtual #17                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        80: astore        12
        82: iload_2
        83: ireturn                        //13  返回结果

Guess you like

Origin blog.csdn.net/qq_43141726/article/details/115288927