1. Conditional judgment instruction
instruction | mnemonics | meaning |
---|---|---|
0x99 | ifeq | Check if == 0 |
0x9a | ifne | Judge whether or not! = 0 |
0x9b | iflt | Check if it is less than 0 |
0x9c | ifge | Check whether the value is greater than or equal to 0 |
0x9d | ifgt | Check whether the value is greater than 0 |
0x9e | ifle | Check if <= 0 |
0x9f | if_icmpeq | Whether two ints == |
0xa0 | if_icmpne | Two int yes! = |
0xa1 | if_icmplt | Are two ints < |
0xa2 | if_icmpge | Whether two ints >= |
0xa3 | if_icmpgt | Two int is > |
0xa4 | if_icmple | Whether two ints <= |
0xa5 | if_acmpeq | Whether two references == |
0xa6 | if_acmpne | Two references if! = |
0xc6 | ifnull | Check whether == null |
0xc7 | ifnonnull | Judge whether or not! = null |
A few notes:
- Byte, short, and char are all compared as ints because operand stacks are all 4 bytes
- Goto The bytecode used to jump to the specified line number
Case source:
public class Demo3_3 {
public static void main(String[] args) {
int a = 0;
if(a == 0) {
a = 10;
} else {
a = 20; }}}Copy the code
Byte code:
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
Copy the code
Long, float, double, float, float, float, float Reference docs.oracle.com/javase/spec…
2. Cycle control instruction
In fact, the loop control is the same as the previous instructions, such as the while loop:
public class Demo3_4 {
public static void main(String[] args) {
int a = 0;
while (a < 10) { a++; }}}Copy the code
The bytecode is:
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
Copy the code
Or the do while loop:
public class Demo3_5 {
public static void main(String[] args) {
int a = 0;
do {
a++;
} while (a < 10); }}Copy the code
The bytecode is:
0: iconst_0
1: istore_1
2: iinc 1.1
5: iload_1
6: bipush 10
8: if_icmplt 2
11: return
Copy the code
Finally, look at the for loop:
public class Demo3_6 {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
}
}
}
Copy the code
The bytecode is:
0: iconst_0
1: istore_1
2: iload_1
3: bipush 10
5: if_icmpge 14
8: iinc 1.1
11: goto 2
14: retur
Copy the code
Note: comparing the bytecodes of while and for, you can see that they are identical and that the different paths can go the same way
Practice – Judge the results
In bytecode terms, the following code runs:
public class Demo3_6_1 {
public static void main(String[] args) {
int i = 0;
int x = 0;
while (i < 10) {
x = x++;
i++;
}
System.out.println(x); // The result is 0}}Copy the code
4. Construction method
Constructor of class < cinit>()V
public class Demo3_8_1 {
static int i = 10;
static {
i = 20;
}
static {
i = 30; }}Copy the code
The compiler collects all static code blocks and static member assignments from top to bottom and merges them into a special method < cinit>()V:
0: bipush 10 // I = 10
2: putstatic #2 // Field i:I
5: bipush 20
7: putstatic #2 // Field i:I
10: bipush 30
12: putstatic #2 // Field i:I
15: return
Copy the code
The < cinit>()V method is called during the initialization phase of the class load
The final result of this code is 30!
Exercise: students can adjust the position of static variables and static code blocks themselves and observe bytecode changes
< init>()V Instance object constructor
public class Demo3_8_2 {
private String a = "s1";
{
b = 20;
}
private int b = 10;
{
a = "s2";
}
public Demo3_8_2(String a, int b) {
this.a = a;
this.b = b;
}
public static void main(String[] args) {
Demo3_8_2 d = new Demo3_8_2("s3".30);
System.out.println(d.a);// s3
System.out.println(d.b);/ / 30}}Copy the code
The compiler collects all {} code blocks and member variable assignments from top to bottom to form a new constructor, but the code inside the original constructor is always last:
public cn.itcast.jvm.t3.bytecode.Demo3_8_2(java.lang.String, int); descriptor: (Ljava/lang/String; I)V flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=3
0: aload_0
1: invokespecial #1 // super.<init>()V
4: aload_0
5: ldc #2 // <- "s1"
7: putfield #3 // -> this.a
10: aload_0
11: bipush 20 / / < - 20
13: putfield #4 // -> this.b
16: aload_0
17: bipush 10 / / < - 10
19: putfield #4 // -> this.b
22: aload_0
23: ldc #5 // <- "s2"
25: putfield #3 // -> this.a
28: aload_0 // ------------------------------
29: aload_1 // <- slot 1(a) "s3" |
30: putfield #3 // -> this.a |
33: aload_0 |
34: iload_2 // <- slot 2(b) 30 |
35: putfield #4 // -> this.b --------------------
38: return
LineNumberTable: ...
LocalVariableTable:
Start Length Slot Name Signature
0 39 0 this Lcn/itcast/jvm/t3/bytecode/Demo3_8_2;
0 39 1 a Ljava/lang/String;
0 39 2 b I
MethodParameters: ...
Copy the code
5. Method calls
Take a look at the bytecode instructions for several different method calls:
public class Demo3_9 {
public Demo3_9(a) {}private void test1(a) {}private final void test2(a) {}public void test3(a) {}public static void test4(a) {}public static void main(String[] args) {
Demo3_9 d = newDemo3_9(); d.test1(); d.test2(); d.test3(); d.test4(); Demo3_9.test4(); }}Copy the code
Byte code:
0: new #2 // class cn/itcast/jvm/t3/bytecode/Demo3_9
3: dup
4: invokespecial #3 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokespecial #4 // Method test1:()V
12: aload_1
13: invokespecial #5 // Method test2:()V
16: aload_1
17: invokevirtual #6 // Method test3:()V
20: aload_1
21: pop
22: invokestatic #7 // Method test4:()V
25: invokestatic #7 // Method test4:()V
28: return
Copy the code
- New creates an object, allocates heap memory to the object, and pushes the object reference onto the operand stack.
- Dup is the content at the top of the assignment operand stack. In this example, it is the object reference. Why do we need two references? ()V (consumes one reference at the top of the stack) and the other is assigned to the local variable in conjunction with astore_1.
- The final method, private method and constructor are all called by the Invokespecial instruction, which belong to static binding.
- The ordinary member method is called by Invokevirtual and is dynamically bound, i.e. supports polymorphism.
- Another difference between a member method and a static method call is whether an object reference is required before the method is executed.
- More interesting is d.test4(); Call a static method through an object reference. Invokestatic previously executed the pop instruction, dropping the object reference from the operand stack.
- Another case where invokespecial is executed is when a superclass method is called through super.
6. Principle of polymorphism
/** * -XX:-UseCompressedOops -XX:-UseCompressedClassPointers */
public class Demo3_10 {
public static void test(Animal animal) {
animal.eat();
System.out.println(animal.toString());
}
public static void main(String[] args) throws IOException {
test(new Cat());
test(newDog()); System.in.read(); }}abstract class Animal {
public abstract void eat(a);
@Override
public String toString(a) {
return "I am" + this.getClass().getSimpleName(); }}class Dog extends Animal {
@Override
public void eat(a) {
System.out.println("Bone gnawing"); }}class Cat extends Animal {
@Override
public void eat(a) {
System.out.println("Fish"); }}Copy the code
1) Run the code
Stop on the system.in.read () method and run JPS to get the process ID
2) Run the HSDB tool, go to the JDK installation directory, and run:
java -cp ./lib/sa-jdi.jar sun.jvm.hotspot.HSDB
Copy the code
Attach the process ID to the GUI and open Tools -> Find Object By Query:
Input the select d from cn. Itcast. The JVM. T3. The bytecode. Dog d click Execute
4) View the object memory structure
Click on the hyperlink to see the memory structure of the object, which has no attributes, so only 16 bytes of the object header, with the first 8 bytes being
MarkWord, the last 8 bytes are the Class pointer to the object, but its actual address is not currently visible
You can use Windows -> Console to enter the CLI mode and run
mem 0x00000001299b4978 2
Copy the code
Mem takes two arguments: argument 1 is the address of the object and argument 2 is the view of 2 lines (16 bytes)
The second line 0x000000001b7d4028 is the memory address of Class
6) View the class vtable
- Method 1: Enter the Inspector with Alt+R and type in the memory address of the Class
- Method 2: or Tools -> Class Browser type Dog search to get the same result
Either way, you can find that the vtable of the Dog Class has a length of 6, meaning that the Dog Class has 6 virtual methods (polymorphic, final, static are not included).
So who are these six methods? Start from the start address of Class. Offset 0x1b8 is the start address of vtable.
0x000000001b7d4028
1b8 +
---------------------
0x000000001b7d41e0
Copy the code
On Windows -> Console, go to the CLI and run
mem 0x000000001b7d41e0 6
0x000000001b7d41e0: 0x000000001b3d1b10
0x000000001b7d41e8: 0x000000001b3d15e8
0x000000001b7d41f0: 0x000000001b7d35e8
0x000000001b7d41f8: 0x000000001b3d1540
0x000000001b7d4200: 0x000000001b3d1678
0x000000001b7d4208: 0x000000001b7d3fa8
Copy the code
You get the entry addresses of the six virtual methods
7) Verify method address
Use Tools -> Class Browser to view the method definitions of each Class
Dog - public void eat(a) @0x000000001b7d3fa8
Animal - public java.lang.String toString(a) @0x000000001b7d35e8;
Object - protected void finalize(a) @0x000000001b3d1b10;
Object - public boolean equals(java.lang.Object) @0x000000001b3d15e8;
Object - public native int hashCode(a) @0x000000001b3d1540;
Object - protected native java.lang.Object clone(a) @0x000000001b3d1678;
Copy the code
Sit down and find out
- The eat() method is Dog’s own
8) summary
When executing invokevirtual instructions:
- The object is first found by the object reference in the stack frame.
- Analyze the object header to find the actual Class of the object.
- The Class structure has the VTable, which is generated at the link stage of the Class load based on the method rewrite rules.
- Look up the table for the exact address of the method.
- Execute the bytecode of the method.