首先,今天简单分享一下JVM的常见指令,在此之前有一个问题,以下代码块的值是多少:
public class JvmTest1 {
public static void main(String[] args) {
int i = 0;
i = i++;
System.out.println(i);
}
}
在此先留个疑问?是1还是0呢?好难猜啊
首先,来学习一些基础的字节码指令用于后续解答这个问题:
第一个指令是: iconst_[操作数],例如iconst_0,表示将0这个字面量放到一个临时的操作数栈中;第二个指令是:istore_[索引],例如istore_1,表示将操作数栈中的数字弹出到一个局部变量表(数组)的1号索引上;
第三个指令是:iload_[索引],例如iload_1,表示将局部变量表的索引为1的值复制一份到操作数栈中;
第四个指令是:iinc [索引] by 数字,例如:iinc 1 by 1,注意减法其实就是iinc 1 by -1,表示将局部变量表的1号索引对应的值加1;
第五个指令是:return,表示结束。
好的,前置知识已经掌握,我们来分析一下上面代码的字节码指令,我们将该代码用jclasslib工具打开,我这里是直接在idea插件中下载的,因为这样直接使用比较方便。我们打开编译后的字节码文件看看:
选择到方法目录下的main下面的code查看该main方法的字节码指令,通过前置知识的分析,我们可以发现:
第一行指令:iconst_0,将0这个数字放到了操作数栈中。
第二行指令:istore_1,将栈中的元素弹出,并放到索引位置为1的地方。
第三行指令:iload_1,将局部变量表索引1的位置的对应的值放到操作数栈中。
第四行指令:iinc 1 by 1,表示局部变量表的1号位置值加一。
第五行指令:istore_1,表示将操作数栈中的值放到局部变量的1号位置,也就是将0放到了1号位置。 剩余指令就是取值打印并退出的指令不再赘述,通过指令分析我们发现,局部变量表中的值变为了0。
所以前面的问题答案也就出来了,大家也可以去尝试把i++换成++i,来练习一下这些常见的指令。