[JVM] bytecode instructions

1. The execution flow of the method

raw java code

public class Demo3_1 {
    
    
    public static void main(String[] args) {
    
    
        int a = 10;
        int b = Short.MAX_VALUE + 1;
        int c = a + b;
        System.out.println(c);
    }
}

compiled bytecode file

[root@localhost ~]# javap -v Demo3_1.class
Classfile /root/Demo3_1.class
Last modified Jul 7, 2019; size 665 bytes
MD5 checksum a2c29a22421e218d4924d31e6990cfc5
Compiled from "Demo3_1.java"
public class cn.itcast.jvm.t3.bytecode.Demo3_1
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #7.#26 // java/lang/Object."<init>":()V
#2 = Class #27 // java/lang/Short
#3 = Integer 32768
#4 = Fieldref #28.#29 //
java/lang/System.out:Ljava/io/PrintStream;
#5 = Methodref #30.#31 // java/io/PrintStream.println:(I)V
#6 = Class #32 // cn/itcast/jvm/t3/bytecode/Demo3_1
#7 = Class #33 // java/lang/Object
#8 = Utf8 <init>
#9 = Utf8 ()V
#10 = Utf8 Code
#11 = Utf8 LineNumberTable
#12 = Utf8 LocalVariableTable
#13 = Utf8 this
#14 = Utf8 Lcn/itcast/jvm/t3/bytecode/Demo3_1;
#15 = Utf8 main
#16 = Utf8 ([Ljava/lang/String;)V
#17 = Utf8 args
#18 = Utf8 [Ljava/lang/String;
#19 = Utf8 a
#20 = Utf8 I
#21 = Utf8 b
#22 = Utf8 c
#23 = Utf8 MethodParameters
#24 = Utf8 SourceFile
#25 = Utf8 Demo3_1.java
#26 = NameAndType #8:#9 // "<init>":()V
#27 = Utf8 java/lang/Short
#28 = Class #34 // java/lang/System
#29 = NameAndType #35:#36 // out:Ljava/io/PrintStream;
#30 = Class #37 // java/io/PrintStream
#31 = NameAndType #38:#39 // println:(I)V
#32 = Utf8 cn/itcast/jvm/t3/bytecode/Demo3_1
#33 = Utf8 java/lang/Object
#34 = Utf8 java/lang/System
#35 = Utf8 out
#36 = Utf8 Ljava/io/PrintStream;
#37 = Utf8 java/io/PrintStream
#38 = Utf8 println
#39 = Utf8 (I)V
{
public cn.itcast.jvm.t3.bytecode.Demo3_1();
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 6: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcn/itcast/jvm/t3/bytecode/Demo3_1;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: bipush 10
2: istore_1
3: ldc #3 // int 32768
5: istore_2
6: iload_1
7: iload_2
8: iadd
9: istore_3
10: getstatic #4 // Field
java/lang/System.out:Ljava/io/PrintStream;
13: iload_3
14: invokevirtual #5 // Method
java/io/PrintStream.println:(I)V
17: return
LineNumberTable:
line 8: 0
line 9: 3
3)常量池载入运行时常量池
4)方法字节码载入方法区
5)main 线程开始运行,分配栈帧内存
(stack=2,locals=4)
line 10: 6
line 11: 10
line 12: 17
LocalVariableTable:
Start Length Slot Name Signature
0 18 0 args [Ljava/lang/String;
3 15 1 a I
6 12 2 b I
10 8 3 c I
MethodParameters:
Name Flags
args
}

1.1 Load the constant pool into the runtime constant pool

First, the class where the main method is located will be loaded by the class loader of the JVM.

That is, the bytecode file is read into memory. The data in this part of the constant pool will be placed in the runtime constant pool of the memory.

Students who don’t know what a runtime constant pool is can take a look at this [JavaSE] Analysis of String and StringTable

image-20230306223426646

Some relatively small numbers, such as 10, are not stored in the runtime constant pool, but are stored together with the bytecode instructions of the method.

Once this number exceeds the maximum value of an integer ( Short.MAX_VALUE), it will be stored in the constant pool.


1.2 Load method bytecode into method area

Some bytecodes of the method will be placed in the method area

image-20230306224057252


1.3 The main thread starts running and allocates stack frame memory

There are two things in the stack frame, namely the local variable table and the operand stack.

The size of these two things has been specified in the bytecode file.

Code:
stack=2, locals=4, args_size=1

That is, the operand stack is 2, and the local variable table is 4.

image-20230306224233281


1.4 The execution engine starts to execute the bytecode

According to the bytecode file in the method area, the execution flow is as follows.

Executionbipush 10 , this instruction means to push a byte into the operand stack (its length will be filled with 4 bytes), and there are similar instructions

  • sipushPush one shortonto the operand stack (its length will be padded to 4 bytes)
  • ldcPush one intonto the operand stack
  • ldc_wPush one longinto the operand stack (in two pushes, because longit is 8 bytes)
  • The small numbers are stored together with the bytecode instructions, and shortthe numbers beyond the range are stored in the constant pool

image-20230307104059705

Then, executeistore_1 , the meaning of this forest is to store in the local variable tableslot 1

image-20230307104317435

ldc #3, this instruction loads data from the constant pool #3into the operand stack

image-20230307104435272

istore2, and then place 32768 in the operand stack in slot 2 of the local variable table.

image-20230307104554000

iload1 与 iload2The instruction is to place the data in the No. 1 and No. 2 positions of the local variable table into the operand in sequence

image-20230307104711304

image-20230307104719638

isadd, this instruction corresponds to the addition operation, the execution engine will execute it add, and two variables will pop up from the operand stack. addAfter the execution engine completes the operation, it will be pushed into the operand stack again

image-20230307105020947

istore 3Then pop the variable in the operand stack and place it in position 3, that is, assign it to c

image-20230307105107244

getstatic #4, find a static object in the constant pool, load it into the operand, and then load 3push the data in slot 3 into the operand, invokevirtual #5the instruction is to find item #5 of the constant pool, locate the method java/io/PrintStream.println(I)and generate a new stack frame, Pass the parameters and execute the bytecode of the new stack frame

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-B9AX35Ax-1678159317918)(https://lnnu-tuchuang.oss-cn-guangzhou.aliyuncs.com/img /image-20230307105849420.png)]

After execution, the stack frame is popped and the contents of the main operand stack are cleared.

image-20230307105927217

Finally, return completes the call of the main method, pops up the main stack frame, and ends the program.


2. Condition judgment

The instruction for conditional judgment is shown in the figure below

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-XCr9T3UI-1678159317919)(https://lnnu-tuchuang.oss-cn-guangzhou.aliyuncs.com/img /image-20230307110332183.png)]

It should be noted that byte, short, and char will be compared as int, because the operand stack is 4 bytes


2.1 Source code analysis

public class Demo3_3 {
    
    
    public static void main(String[] args) {
    
    
        int a = 0;
        if(a == 0) {
    
    
            a = 10;
        } else {
    
    
            a = 20;
        }
    }
}
0: iconst_0
1: istore_1
2: iload_1
3: ifne 12
6: bipush 10
8: istore_1
9: goto 15
12: bipush 20
14: istore_1
15: return
  1. iconst_0, get a constant of 0 and push it into the operand stack
  2. istore_1, put this element of the operand stack in position 1 of the local variable table, that is, assign a value of 0
  3. iload_1, and then push the value of a onto the operand stack
  4. ifne 12, to judge whether ==0
    1. If !=0, then jump to the middle area of ​​the 12-line bytecode instruction bipush 20, that is, push 20 into the operand stack, istore_1and assign a to 20.
    2. If it is ==0, it is to continue to execute bipush 10and istore_1, assign a to 10, and goto 15when executing, skip to line 15return

3. Loop control instruction

The loop control instruction is actually similar to the conditional judgment, but it uses gotothe loop


3.1 Source code analysis

public class Demo3_4 {
    
    
    public static void main(String[] args) {
    
    
        int a = 0;
        while (a < 10) {
    
    
            a++;
        }
    }
}
0: iconst_0
1: istore_1
2: iload_1
3: bipush 10
5: if_icmpge 14
8: iinc 1, 1
11: goto 2
14: return
  1. iconst_0And istore_1, assign a to 0.
  2. iload_1Push the value of a onto the operand stack
  3. bipush 10, push 10 onto the operand stack
  4. if_icmpge 14, to judge whether the two ints are true >=, if not, then jump to the 14th line of instructions
  5. If it is established, then iinc 1, 1the No. 1 position of the local variable table is incremented by 1, and then goto 2continues to jump back to the No. 2 position.

Reference: Dark Horse Programmer JVM complete tutorial, quick introduction to Java virtual machine, dry goods without procrastination)

Guess you like

Origin blog.csdn.net/weixin_51146329/article/details/129378957