通过字节码分析finally面试题
首先我们先来看两道面试题
1 | public class Demo2_2 { |
1 | public class Demo2_3 { |
问两道题分别输出什么?为什么?
我们分开来看,先看第一道题
利用javap -v 指令生成字节码, 为了方便观看,我们只留test方法.
这里相比之前的字节码多了一个Exception table, 是用来实现异常处理.
我们来逐行分析字节码
1 | public static int test(); |
这里,我们可以看到:
- 无论是try代码块,还是cache代码块,在编译期,都会在其后面追加上finally代码块的代码,以保障finall一定执行,因为一个方法只能有一个return,所以前面的return在编译期被优化了.
- 为了保证finally代码块无论什么情况都要执行,所以利用了异常表,来保障,即使在try中发生了未cache的异常,或者在cache中发生异常,finally代码块都会执行.
- finally代码块,如果有retrun的话,发生异常可能被忽略,没有throw出去.这个例子中,如果cache中发生异常,或者try中发生为捕获的异常,但是却没有throw出去.所以,尽量不要在finally中写return.
- 在编译期,显示局部变量表长度为3,但是反编译结果却只有1个.这可能是由于后面两个变量无法确定名称导致.
现在,我们知道了第一道题的答案:输出结果为30.
然后我们再看第二道题
还是先用javap -v 来反编译
同样我们值保留test()方法
然后来逐行分析
1 | public static int test(); |
这里,我们可以看出:
- 在finally中修改return的属性时,我们会先复制一份放入局部变量表,然后修改原有数据,将复制的数据return
- 如果finally中没有retrurn,则出现异常时,finally中会主动throw掉.
以上仅为个人观点,如有错误,欢迎指正.谢谢!