本篇指令码表,参考自ASM文档手册,如果你对asm感兴趣,可到ASM官网下载手册学习。
一、本地变量操作指令(I,L,F,D,A这些前缀表示对int,long,float,double,引用进行操作)
本地变量指令集
指令
意义
ILOAD_n(0~3), LLOAD_n(0~3), FLOAD_n(0~3), DLOAD_n(0~3)
超过三的 直接 xLoad n,如ILOAD 4,LLOAD 5
将局部变量表中第n个槽的(int|long|float|double)类型变量推送到操作数栈
ALOAD_n(0~3)
超过3的 ALOAD n,如:ALOAD 5
将引用类型的局部变量第n个槽的推送到操作数栈
ISTORE_n(0~3), LSTORE_n(0~3), FSTORE_n(0~3), DSTORE_n(0~3)
超过三的xSTORE n
将操作数栈顶的(int|long|float|double)类型值弹出存到局部变量表的第n个槽中
ASTORE_n(0~3)
超过3的 ASTORE n
将栈顶引用类型的值存到局部变量表中的第n个槽中
IINC var incr 将局部变量表中的第var个变量增加incr,并把新值存到局部变量表
本地变量操作表对应的下标是从0开始的,比如下面一段程序
public void print(int age) {
int a = age;
a++;
}
对应的字节码文件
stack=1, locals=3, args_size=2//这里的参数为什么是2,因为参数里面有个this,这个this是隐藏的,在JVM中是以参数的形式传递进去的
iload_1//将局部变量表中的第1个槽,也就是age这个值,0是this,压入操作数栈栈顶
istore_2//将操作数栈顶的值,这里就是age,存到局部变量表的第二个槽,也就是a
iinc 2, 1//将局部变量表中的第二个槽的a加1
return//方法返回
注意,如果局部变量中有long或者double类型的值,那么会占用局部变量两个槽,如有局部变量int age,long l, double d, short s, byte b,那么对应的槽应该是1,2,4,6,7
byte,short,char,int,boolean类型的操作指令统一使用ILOAD或者ISTORE这些指令
二、栈操作指令
指令 栈操作前 栈操作后
POP
... , v
... (v被弹出)
POP2
... , v1 , v2
... (v1和v2被弹出)
... , w
... (w表示占用两个槽的变量,如long,double之类)
DUP
... , v
... , v , v (复制一份)
DUP2
... , v1 , v2
... , v1 , v2 , v1 , v2 (复制栈中的两个值)
... , w
... , w, w (复制一个long,double型的)
SWAP
... , v1 , v2
... , v2, v1 交换
DUP_X1
... , v1 , v2
... , v2 , v1 , v2 复制栈顶值v2,并弹出v1,v2,然后压入v1,v2
DUP_X2
... , v1 , v2 , v3
... , v3 , v1 , v2 , v3 复制v3,并将弹出的3个值入栈
... , w , v
... , v, w , v 复制v,并将复制的两个值入栈(W占两槽)
DUP2_X1
... , v1 , v2 , v3
... , v2 , v3 , v1 , v2 , v3 复制两个值,并将弹出的3个值入栈
... , v , w
... , w, v , w 复制2个值,并将弹出的两个值入栈,w占两个槽
DUP2_X2
... , v1 , v2 , v3 , v4
... , v3 , v4 , v1 , v2 , v3 , v4 复制2值,将弹出的4个值入栈
... , w , v1 , v2
... , v1, v2, w , v1 , v2 复制2值,将弹出的三个值入栈
.... , v1 , v2 , w
... , w, v1 , v2 , w 复制1个值,将弹出的3个值入栈
... , w1 , w2
... , w2, w1 , w2 复制1个值,将弹出的1个值入栈
举个例子
public void print(int age, String name) {
this.age = age;
this.name = name;
}
对应的字节码指令
aload_0 //将this入栈
dup //复制一个this
aload_1 //将age入栈
putfield #n //给age复制,这里的n表示一个数字,#n表示索引,对应常量池中的常量
aload_2 //将name入栈
putfield #n //给name复制
三、常量操作
ICONST_n (−1 ≤ n ≤ 5)
...
... , n 将整型常量n入栈
LCONST_n (0 ≤ n ≤ 1)
...
... , nL将长整型常量n入栈
FCONST_n (0 ≤ n ≤ 2)
...
... , nF将float常量入栈
DCONST_n (0 ≤ n ≤ 1)
...
... , nD 将double常量入栈
BIPUSH b, −128 ≤ b
...
... , b 将byte常量入栈
SIPUSH s, −32768 ≤ s
...
... , s将短整型入栈
LDC cst(int, float, long, double, String or Type)
...
... , cst 将常量池中值入栈
ACONST_NULL
...
... , null 将null值入栈
如:public void print(){
int a1 = 1; //ICONST_1将1入栈
//ISTORE_1 将1存入局部变量表1中,即a1
int a2 = 10; //BIPUSH 10
//ISTORE 2
int a3 = 100; // SIPUSH 100
//ISTORE 3
float a4 = 123f; //LDC #4这个#4是引用了常量池里的值,123
//FLOAD 4
}
四、算术和逻辑操作指令
IADD, LADD, FADD, DADD
... , a , b
... , a + b 将栈顶的两个值相加,并把结果入栈
ISUB, LSUB, FSUB, DSUB
... , a , b
... , a - b
IMUL, LMUL, FMUL, DMUL
... , a , b
... , a * b
IDIV, LDIV, FDIV, DDIV
... , a , b
... , a / b
IREM, LREM, FREM, DREM
... , a , b
... , a b
INEG, LNEG, FNEG, DNEG
... , a
... , -a
ISHL, LSHL
... , a , n
... , a <
ISHR, LSHR
... , a , n
... , a >> n
IUSHR, LUSHR
... , a , n
... , a >>> n
IAND, LAND
... , a , b
... , a & b
IOR, LOR
... , a , b
... , a | b
IXOR, LXOR
... , a , b
... , a ^ b
LCMP
... , a , b
... , a == b ? 0 : (a < b ? -1 : 1)
FCMPL, FCMPG
... , a , b
... , a == b ? 0 : (a < b ? -1 : 1)
DCMPL, DCMPG
... , a , b
... , a == b ? 0 : (a < b ? -1 : 1)
五、转换
I2B
... , i
... , (byte) i
I2C
... , i
... , (char) i
I2S
... , i
... , (short) i
L2I, F2I, D2I
... , a
... , (int) a
I2L, F2L, D2L
... , a
... , (long) a
I2F, L2F, D2F
... , a
... , (float) a
I2D, L2D, F2D
... , a
... , (double) a
CHECKCAST class
... , o
... , (class) o
六、对象,字段,方法操作
NEW class
...
... , new class
GETFIELD c f t
... , o
... , o.f
PUTFIELD c f t
... , o , v
...
GETSTATIC c f t
...
... , c.f
PUTSTATIC c f t
... , v
...
INVOKEVIRTUAL c m t
... , o , v1 , ... , vn
... , o.m(v1, ... vn)
INVOKESPECIAL c m t
... , o , v1 , ... , vn
... , o.m(v1, ... vn)
INVOKESTATIC c m t
... , v1 , ... , vn
... , c.m(v1, ... vn)
INVOKEINTERFACE c m t
... , o , v1 , ... , vn
... , o.m(v1, ... vn)
INVOKEDYNAMIC m t bsm
... , o , v1 , ... , vn
... , o.m(v1, ... vn)
INSTANCEOF class
... , o
... , o instanceof class
MONITORENTER
... , o
...
MONITOREXIT
... , o
...
七、数组操作
NEWARRAY type (for any primitive type) new基本类型的数组
... , n 数组长度
... , new type[n] new出来的数组引用
ANEWARRAY class new引用类型的数组
... , n 数组长度
... , new class[n]
MULTIANEWARRAY [...[t n 多维数组
... , i1 , ... , in 各维长度
... , new t[i1]...[in]...
BALOAD, CALOAD, SALOAD 将指定下标的值入栈
... , o , i i下标,o数组
... , o[i]
IALOAD, LALOAD, FALOAD, DALOAD
... , o , i
... , o[i]
AALOAD
... , o , i
... , o[i]
BASTORE, CASTORE, SASTORE
... , o , i , j
...
IASTORE, LASTORE, FASTORE, DASTORE
... , o , i , a
...
AASTORE
... , o , i , p
...
ARRAYLENGTH
... , o
... , o.length
八、跳转语句
IFEQ
... , i
...
jump if i == 0
IFNE
... , i
...
jump if i != 0
IFLT
... , i
...
jump if i
IFGE
... , i
...
jump if i >= 0
IFGT
... , i
...
jump if i > 0
IFLE
... , i
...
jump if i <= 0
IF_ICMPEQ
... , i , j
...
jump if i == j
IF_ICMPNE
... , i , j
...
jump if i != j
IF_ICMPLT
... , i , j
...
jump if i < j
IF_ICMPGE
... , i , j
...
jump if i >= j
IF_ICMPGT
... , i , j
...
jump if i > j
IF_ICMPLE
... , i , j
...
jump if i <= j
IF_ACMPEQ
... , o , p
...
jump if o == p
IF_ACMPNE
... , o , p
...
jump if o != p
IFNULL
... , o
...
jump if o == null
IFNONNULL
... , o
...
jump if o != null
GOTO
...
...
jump always
TABLESWITCH
... , i
...
jump always
LOOKUPSWITCH
... , i
...
jump always
九、return
IRETURN, LRETURN, FRETURN, DRETURN
... , a
ARETURN
... , o
RETURN
...
ATHROW
... , o
十、泛型
如:public class Test ==>
public class Test extends ArrayList ==> Ljava/util/ArrayList;
static Class extends T> m (int n) ==> (I)Ljava/lang/Class;
List==> Ljava/util/List;
List>==> Ljava/util/List;
List extends Number>==> Ljava/util/List;
List super Integer>==> Ljava/util/List;
List[]>==> Ljava/util/List;>;
HashMap.HashIterator==> Ljava/util/HashMap.HashIterator;
注意:如果是定义定义泛型,比如class Test,方法中的这类T,在写泛型签名的时候应当写成T:Ljava/lang/Object;而不是TT;在其他非定义泛型的位置,写成TT;
十一、描述符表
java类型
类型描述符
boolean
Z
char
C
byte
B
short
S
int
I
long
J
float
F
double
D
Object
Ljava/lang/Object;
int[]
[I
Object[][]
[[Ljava/lang/Object;
十二、方法描述符
方法
方法描述符
void m(int i, float f)
(IF)V
int m(Object o)
(Ljava/lang/Object;)I
int[] m(int i, String s)
(ILjava/lang/String;)I
Object m(int[] i)
([I)Ljava/lang/Object;