JVM | 字节码指令基础
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM | 字节码指令基础相关的知识,希望对你有一定的参考价值。
-
操作数栈管理指令
1)pop、pop2:将操作数栈的栈顶一个或两个元素出栈。
2)dup、dup2、dup_x1、dup2_x1、dup_x2、dup2_x2:复制栈顶一个或两个数值并将复制值或双份的复制值重新压入栈顶。
3)swap:将栈最顶端两个数值互换。
public static void main(String[] args) {
heavyMethod();
}
对应的字节码:
public static void main(java.lang.String[]);
Signature: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: invokestatic #23 // Method heavyMethod:()I
3: pop
4: return
LineNumberTable:
line 115: 0
line 116: 4
-
加载、存储指令
1)iload、iload<n>、lload、lload<n>、fload、fload<n>、dload、dload<n>、aload、aload<n>:将一个局部变量加载到操作数栈。
2)istore、istore<n>、lstore、lstore<n>、fstore、fstore<n>、dstore、dstore<n>、astore、astore<n>:将一个数值从操作数栈存储到局部变量表。
3)bipush、sipush、ldc、ldc_w、ldc2_w、aconst_null、iconstm1、iconst<i>、lconst<l>、fconst<f>、dconst_<d>:将一个常量加载到操作数栈。
4)wide:扩充局部变量表的访问索引的指令。
public static int methodE(){
int e = 100;
int c = 300;
int d = 300000;
e++;
++e;
--e;
e--;
return c + d + e;
}
对应的字节码:
public static int methodE();
Signature: ()I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=0
0: bipush 100
2: istore_0
3: sipush 300
6: istore_1
7: ldc #5 // int 300000
9: istore_2
10: iinc 0, 1
13: iinc 0, 1
16: iinc 0, -1
19: iinc 0, -1
22: iload_1
23: iload_2
24: iadd
25: iload_0
26: iadd
27: ireturn
LineNumberTable:
line 40: 0
line 41: 3
line 42: 7
line 43: 10
line 44: 13
line 45: 16
line 46: 19
line 47: 22
-
运算指令
1)iadd、ladd、fadd、dadd:加法指令。
2)isub、lsub、fsub、dsub:减法指令。
3)imul、lmul、fmul、dmul:乘法指令。
4)idiv、ldiv、fdiv、ddiv:除法指令。
5)irem、lrem、frem、drem:求余指令。
6)ineg、lneg、fneg、dneg:取反指令。
7)ishl、ishr、iushr、lshl、lshr、lushr:位移指令。
8)ior、lor:按位或指令。
9)iand、land:按位与指令。
10)ixor、lxor:按位异或指令。
11)iinc:局部变量自增指令。
12)dcmpg、dcmpl、fcmpg、fcmpl、lcmp:比较指令。
参照上例。
-
类型转换指令
1)int类型到long、float或者double类型,long类型到float、double类型,float类型到double类型:宽化类型转换(虚拟机直接支持)。
2)i2b、i2c、i2s、l2i、f2i、f2l、d2i、d2l、d2f:窄化类型转换(显式指令)。
public static void methodK(){
int i = 97;
short i2s = (short) i;
char i2c = (char) i;
long i2l = i;
float i2f = i;
double i2d = i;
float l2f = i2l;
double l2d = i2l;
}
对应的字节码:
public static void methodK();
Signature: ()V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=11, args_size=0
0: bipush 97
2: istore_0
3: iload_0
4: i2s
5: istore_1
6: iload_0
7: i2c
8: istore_2
9: iload_0
10: i2l
11: lstore_3
12: iload_0
13: i2f
14: fstore 5
16: iload_0
17: i2d
18: dstore 6
20: lload_3
21: l2f
22: fstore 8
24: lload_3
25: l2d
26: dstore 9
28: return
LineNumberTable:
line 100: 0
line 101: 3
line 102: 6
line 103: 9
line 104: 12
line 105: 16
line 106: 20
line 107: 24
line 108: 28
-
对象创建与访问指令
1)new :创建类实例的指令。
2)newarray、anewarray、multianewarray:创建数组的指令。
3)getstatic、putstatic、getfield、putfield:访问类字段(类变量)和实例字段(实例变量)的指令。
4)baload、caload、saload、iaload、laload、faload、daload、aaload:把一个数组元素加载到操作数栈的指令。
5)bastore、castore、sastore、iastore、lastore、fastore、dastore、aastore:把一个操作数栈的值存储到数组元素中的指令。
6)arraylength:取数组长度的指令。
7)instanceof、checkcast:检查类实例类型的指令。
public static void methodJ(){
new SimpleMethodExecuteProcess();
System.out.println(SimpleMethodExecuteProcess.i);
}
对应的字节码:
public static void methodJ();
Signature: ()V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=0, args_size=0
0: new #9 // class edu/atlas/demo/java/jvm/SimpleMethodExecuteProcess
3: dup
4: invokespecial #10 // Method "<init>":()V
7: pop
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: getstatic #11 // Field i:I
14: invokevirtual #12 // Method java/io/PrintStream.println:(I)V
17: return
LineNumberTable:
line 91: 0
line 93: 8
line 94: 17
-
控制转移指令
1)ifeq、iflt、ifle、ifne、ifgt、ifge、ifnull、ifnonnull、if_icmpeq、if_icmpne、if_icmplt、if_icmpgt、if_icmple、if_icmpge、if_acmpeq、if_acmpne:条件分支。
2)tableswitch、lookupswitch:复合条件分支。
3)goto、goto_w、jsr、jsr_w、ret:无条件分支。
public static void methodG(){
if(i == 0){
System.out.println(System.currentTimeMillis());
}
while(i < 1){
System.out.println(System.currentTimeMillis());
i++;
}
}
对应的字节码:
public static void methodG();
Signature: ()V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=0, args_size=0
0: getstatic #6 // Field i:I
3: ifne 15
6: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
9: invokestatic #7 // Method java/lang/System.currentTimeMillis:()J
12: invokevirtual #8 // Method java/io/PrintStream.println:(J)V
15: getstatic #6 // Field i:I
18: iconst_1
19: if_icmpge 42
22: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
25: invokestatic #7 // Method java/lang/System.currentTimeMillis:()J
28: invokevirtual #8 // Method java/io/PrintStream.println:(J)V
31: getstatic #6 // Field i:I
34: iconst_1
35: iadd
36: putstatic #6 // Field i:I
39: goto 15
42: return
LineNumberTable:
line 62: 0
line 63: 6
line 66: 15
line 67: 22
line 68: 31
line 70: 42
StackMapTable: number_of_entries = 2
frame_type = 15 /* same */
frame_type = 26 /* same */
-
异常处理指令
athrow :显式抛出异常指令。
public static void methodH(){
try {
throw new NullPointerException("nothing ...");
// do nothing ...
} catch (Throwable t){
// do nothing ...
}
}
对应的字节码:
public static void methodH();
Signature: ()V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=1, args_size=0
0: new #9 // class java/lang/NullPointerException
3: dup
4: ldc #10 // String nothing ...
6: invokespecial #11 // Method java/lang/NullPointerException."<init>":(Ljava/lang/String;)V
9: athrow
10: astore_0
11: return
Exception table:
from to target type
0 10 10 Class java/lang/Throwable
LineNumberTable:
line 77: 0
line 79: 10
line 82: 11
StackMapTable: number_of_entries = 1
frame_type = 74 /* same_locals_1_stack_item */
stack = [ class java/lang/Throwable ]
-
同步指令
monitorenter、monitorexit:支持synchronized语句块语义的指令。
public void methodI(){
synchronized (Integer.class){
// do nothing ...
}
}
对应的字节码:
public void methodI();
Signature: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=1
0: ldc_w #13 // class java/lang/Integer
3: dup
4: astore_1
5: monitorenter
6: aload_1
7: monitorexit
8: goto 16
11: astore_2
12: aload_1
13: monitorexit
14: aload_2
15: athrow
16: return
Exception table:
from to target type
6 8 11 any
11 14 11 any
LineNumberTable:
line 88: 0
line 90: 6
line 91: 16
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 11
locals = [ class edu/atlas/demo/java/jvm/SimpleMethodExecuteProcess, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
- synchronized 修饰方法的语义解析:可以直接从方法常量池的方法表结构中ACC_SYNCHRONIZED访问标志得知一个方法是否声明为同步方法,不需要解析出monitorenter、monitorexit同步指令。
public static synchronized void methodL(){
int i = 97;
}
public static synchronized void methodL();
Signature: ()V
flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
Code:
stack=1, locals=1, args_size=0
0: bipush 97
2: istore_0
3: return
LineNumberTable:
line 120: 0
line 121: 3
-
方法调用和返回指令
1)invokestatic:调用静态方法。
2)invokespecial:调用实例构造器<init>方法、私有方法和父类方法。
3)invokevirtual:调用所有的虚方法。非虚方法以外的都是虚方法,非虚方法包括使用invokestatic、invokespecial调用的方法和被final修饰的方法。
4)invokeinterface:调用接口方法,运行时再确定一个实现此接口的对象。
5)invokedynamic:用于在运行时动态解析出调用点限定符所引用的方法,并执行该方法。
ireturn(返回值是boolean、byte、char、short、int)、lreturn、freturn、dreturn、areturn:方法返回指令。
public static int heavyMethod(){
int a = 200;
int b = 100;
int c = methodC(methodA(methodA(a, b), b), methodB(a, b));
methodD();
methodE();
methodF();
methodG();
methodH();
new SimpleMethodExecuteProcess().methodI();
methodJ();
methodK();
methodL();
return c;
}
对应的字节码:
public static int heavyMethod();
Signature: ()I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=3, args_size=0
0: sipush 200
3: istore_0
4: bipush 100
6: istore_1
7: iload_0
8: iload_1
9: invokestatic #17 // Method methodA:(II)I
12: iload_1
13: invokestatic #17 // Method methodA:(II)I
16: iload_0
17: iload_1
18: invokestatic #18 // Method methodB:(II)I
21: invokestatic #19 // Method methodC:(II)I
24: istore_2
25: invokestatic #20 // Method methodD:()V
28: invokestatic #21 // Method methodE:()I
31: pop
32: invokestatic #22 // Method methodF:()D
35: pop2
36: invokestatic #23 // Method methodG:()V
39: invokestatic #24 // Method methodH:()V
42: new #14 // class edu/atlas/demo/java/jvm/SimpleMethodExecuteProcess
45: dup
46: invokespecial #15 // Method "<init>":()V
49: invokevirtual #25 // Method methodI:()V
52: invokestatic #26 // Method methodJ:()V
55: invokestatic #27 // Method methodK:()V
58: invokestatic #28 // Method methodL:()V
61: iload_2
62: ireturn
LineNumberTable:
line 128: 0
line 129: 4
line 130: 7
line 131: 25
line 132: 28
line 133: 32
line 134: 36
line 135: 39
line 136: 42
line 137: 52
line 138: 55
line 139: 58
line 140: 61
以上是关于JVM | 字节码指令基础的主要内容,如果未能解决你的问题,请参考以下文章