字节码中的常用指令
一道面试题,问最后输出多少?
public static void main(String[] args) {
int a = 10;
a = a++; // 输出10
//a = ++a; // 输出11
System.out.println(a);
}
上述代码对应的字节码指令
一个main方法对应虚拟机栈的一个栈帧,下面所说的操作数栈就是栈帧中的操作数栈。对变量进行数学运算或者赋值等操作都要把操作数弹出栈。
使用a = a++ 后字节码的指令
- bipush : 将10 压入操作数栈
- istore_1:将10出栈,并赋值给局部变量表中下标为1(下标为0的是 this 变量)的变量a,完成赋值语句。
- iload_1:因为要对a进行赋值操作,把10压入操作数栈。
- iinc 1 by 1:但是在上一步最终完成赋值之前,要对a进行++操作,所以直接将局部变量表中下标为1即变量a进行加1,此时a = 11。
- istore_1:将操作数的的数弹出并赋值给a,a 又变成了10。所以最后输出10
使用a = ++a后的字节码指令
- bipush 10: 将10压入操作数栈
- istore_1:将10出栈,并赋值给局部变量表中下标为1的变量a,完成赋值语句。
- iinc 1 by 1:因为这里是先自加再赋值,所以将a + 1变成11。
- iload_1:现在执行赋值操作,所以先让11入操作数栈。
- istore_1:让11出栈,给a赋值。最终a = 11。
常用指令总结
-
bipush: 压栈
-
iload_x:将局部变量表中下标为x压入栈
-
istore_x:将栈定数据弹出,赋值给局部变量中下标为x的变量
-
iadd:将栈顶两个元素弹出,进行相加操作
-
isub:将栈顶两个元素弹出,进行相减操作
-
invokespecial:执行特殊方法,即不需要多态的方法。
例如:private方法、构造方法
-
invokevirtual:调用方法
-
invokestatic:执行静态方法
.....