某年某月的某一天,群里一位仁兄发了上边的代码。
结果是出人意料的。
下面是这段代码的JVM完整指令
重点是在testt方法,我为当前的栈上的操作数区以及局部变量区做了注释
通过异常表可以看到:3-5行被包在exception里,然后会跳到target:10行,再跳回7直到运行至ireturn,返回值是栈顶的99.
其中仔细看,可以看到99和8都在局部变量区有值,但是到最后要return的时候,JVM把变量99从变量区装载到操作数栈,作为返回值返回了.
--------------------------------------------------------
我把testt方法变一下形
相应的它的JVM代码是
普通的执行顺序:(0-5)->(18-23)->(7-9)
截获异常的执行顺序:(0-5)->(10-13)->(18-23)->(15-17)
结果还是一样,并且既使 return x/0;进入异常,它还是不会把finally里的值正确加入。
-----------------------------------------------
再变一下形
这样正常运行得到的值是99
当把"return x;" 改成"return x/0;"时,会进入catch->finally->第10行return.最后结果是8,为什么呢?
---------------------------------------
马上来揭开答案
再把程序稍微改一下
执行结果是:
x:99______testt():99_____x:8
分析一下结果,刚开始X的值是99
->执行testt()方法
->进入方法的try语句
->执行return x; //这时x被JVM存在了栈区的局部变量栈区里
->然后执行finally里的x=8 //这句更新了全局变量里的static int x,
最后testt方法执行完 JVM会把 try里的这句return的局部变量load到操作数栈.所以结果就清楚了.
把上边程序的 try语句里的"return x;" 改为 return x/0;时执行结果是
x:99______testt():8_____x:8
----------------------------------
后续问题:
这个结果就是2
因为list是一个引用类型,JVM返回的时候 只返回 list的地址,而不是整个list对象
当return list和list.add() 是对一个块堆内存进行的操作.
待续...
简单说一下push store load:
push:将常量入操作数栈
store_x:将操作数栈顶数据弹到x号局部变量
load_x:将x号局部变量装载到操作数栈
ipush前边加i说明是integer类型,还有l(long),f(float),d(double)等,还有a引用类型.