关于JAVA的try catch finally的return返回值问题

时间:2021-11-17 20:20:11

 

某年某月的某一天,群里一位仁兄发了上边的代码。

结果是出人意料的。


下面是这段代码的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引用类型.