Introduction to bytecode
Hello world
public class Helloworld { public static void main(String[] args) { System.out.println("hello,world"); } }
public class com.beetl.myos.ch1.Helloworld { public com.beetl.myos.ch1.Helloworld(); Code: 0: aload_0 1: invokespecial #8 // Method java/lang/Object. "<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #22 // String hello,world 5: invokevirtual #24 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return }
-
Aload_0 This instruction tells the virtual machine to put the local variable this into the operation stack. For each method (the constructor is also a method from the perspective of bytecode, no difference), the parameters of the method and the variables declared in the method are determined during compilation. They are stored in the local variable table of the method stack in the order of occurrence. The position 0 is always reserved for this by default, and the subsequent positions are reserved for the declared parameter list of the method, Then there are local variables reserved for internal use of methods. We will introduce the data structure foundation of instructions in detail in the next section. Here, we only need to know that aload_0 is the first object in the variable list. This is put on the operation stack -
Invokespecial # 8 This instruction tells the virtual machine to call the method in the constant pool, that is, the method java/lang/Object output by javap "<init>": () V. The invokespecial instruction requires an object reference in the Opera nd Stack, that is, this just pushed in through aload_0. The parameters after invokespecial point to the init method of the constant pool. As the name of invokespecial implies, this instruction is only used for some special method calls, such as instance initialization method, private method, parent method
|
|
|
|
-
Return returns without a value. If you need to return an object, use arerun to return an integer. Use ireturn. These instructions require that the operation stack contain a response value. four
-
Getstatic # 16 pushes the static field into the operation stack, and # 16 points to the System.out object in the constant pool -
ldc, Because we know that System.out.println also needs a parameter, the ldc # 22 instruction will push the reference of the string represented by # 22 into the operation stack. -
The invokevirtual instruction is commonly used to call methods, followed by # 24, which is the java/io/PrintStream. println: (Ljava/lang/String;) V method in the constant pool. The invokevirtual instruction will call the first object on the operation stack. The operation stack should look like this
|
|
|
|
|
|
-
Return Return
Operation stack
public class Ch1Simple { public int add(int a,int b){ int c = a+b; return c; } }
public int add(int, int); Code: 0: iload_1 1: iload_2 2: iadd 3: istore_3 4: iload_3 5: ireturn
-
0: iload_1 instruction puts the second element of the variable table into the operation stack. The second element is actually int a. Again, the first element is this, the third element is int b, and the fourth element is int c. This is determined when compiling
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
Iload_2 This instruction puts the third element of the variable into the operation stack -
Iadd wants to add two variables of the operation stack, and i indicates that the two variables of the operation stack are of type int -
The istore_3 operation stack structure is saved back to the variable table, and the location index is 3, that is, the variable c -
Iload_3 Because the method requires a return value, the return instruction still needs to call the operation stack, so variable 3 is pushed into the operation stack -
When the ireturn method finishes executing, the value in the operation stack pops up.
Stack frame
public class Ch1Simple { public int add(int a,int b){ int c = a+b; return c; } }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|