关于jvm的结构之前文章也有说过,这次说一下一些指令
安装jclasslib插件,但是为毛我安装的直接出来是中文版的。。。
int取值0~5时JVM采用iconst_0、iconst_1、iconst_2、iconst_3、iconst_4、iconst_5指令将常量压入栈中,取值-1时采用iconst_m1指令将常量压入栈中。
当int取值-128~127时,JVM采用bipush指令将常量压入栈中。
当int取值-32768~32767采用sipush指令
当int取值-2147483648~2147483647采用 ldc 指令。
所以:
bipush是把6压入栈,注意栈是先进后出的。
istore_1 是弹出操作数栈栈顶元素(这个栈顶元素就是6),保存到局部变量表第1个位置(第一个位置就是 a )
bipush 6 和istore_1 完成了 int a = 6; 也就是先把6压入栈里,然后再弹出到局部变量表索引为1的位置上
iload_1: 把局部变量表里的第一个slot中的整形值复制到操作数栈顶。这时候局部变量表里第一个位置是6,所以拿出来入栈,这个6又进栈了,在栈顶。
iincr 1 by 1: 注意因为上面是 iload_1 ,所以局部变量表里有6,栈里也有6,所以iincr 1by 1是把局部变量表里的6进行了自增1,所以局部变量表里的现在成了7,
istore_1: 是把栈里的6弹出来,保存到局部变量表里的索引为1的位置上,所以那个7又被替换成6了。
getstatic:是运行静态函数打印
iload_1:把局部变量表里的第一个slot中的整形值复制到操作数栈顶。这时候局部变量表里第一个位置是6(由7变成了6),所以拿出来入栈,这个6进栈了,在栈顶。为什么要入栈?因为要打印了,所以打印的是栈里的数据。
istore类似于赋值操作
下面继续几个小例子巩固一下:
bipush:把100压入栈,istore_1:把栈顶的元素100,弹出赋值给局部变量表索引为1的位置,所以a = 100 索引0是参数args。索引1是a
sipush:把300压入栈,istore_2:把栈顶的元素300弹出给局部变量表索引为2的位置。2的位置上是 i,那0和1上放的谁呢?0上放的this,1上放的参数x,因为是成员方法,所以0上永远放的this.然后接下来就是参数
这里需要传参了,但是我没有传,假如x=5,y=6,那么就是iload_1:把局部变量表索引为1位置上的x=5,把5入栈,iload_2:把6入栈,iadd:把6和5弹出栈,做加法运算,然后再把5+6的结果11放入栈顶,istore_3:再把栈顶的11弹出来放到局部变量表索引为3的位置上,索引3号是 i。所以 i=11
new 指令:在堆内存里开辟了一块空间,并且给对象默认值,然后把对象的地址压入栈里。
dup指令:复制对象地址一份,继续压入栈。
所以现在栈里的两个地址都指向堆内存中的那块空间
invokespecial:调用init,执行构造方法的时候,会把dup复制的那个对象地址从栈里弹出去,因为执行构造方法的时候,会告诉虚拟机哪个对象执行,所以会吧这个对象地址弹出来。所以执行完invokespecial的时候,对象里的里面的值就会赋初始值了,对象就构造完成了。
然后astore_1:把栈里的对象地址弹出来赋值给 t (假如后面有代码t调用xx方法的话,那么接下来就是aload_1,继续进栈才能调用xx方法,执行xx方法的时候,又要出栈)
当执行完test方法的时候,会return test方法里的值,是5,因为传参就传了5,所以这个5就进了main方法的栈顶,不管有没有用都会pop把5从main方法的栈顶弹出来。
后续还有很多指令,遇到了再说
网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。
加入交流群
请使用微信扫一扫!