当前位置: 首页 > 科技观察

面试官太难伺候?一个try-catch问了这么多tricks

时间:2023-03-21 15:33:08 科技观察

刚面试回来的B哥又在吐槽了:现在的面试官太难伺候了,放好堆,栈,方法区不用问,让我从让他从字节码的角度来分析一下try-catch-finally(以下简称TCF)的执行效率……我觉得应该是面试官在面试的时候看到大家的千篇一律的套路,以及觉得没问题有必要就转个弯来考大家的理解。今天趁B哥在,总结一下TCF相关的知识点,期待下一次和面试官的50/50对决!环境准备:IntelliJIDEA2020.2.3,JDK1.8.0_181执行顺序先写个简单的代码:publicstaticinttest1(){intx=1;尝试{返回x;}最后{x=2;}}答案是1而不是2,你答对了吗?大家都知道在TCF中,在执行return的时候,会先执行finally中的操作,return之后再执行return,那么为什么这里是1呢?让我们反编译字节码文件。命令:javap-vxxx.class字节码指令晦涩难懂,下面用图解说明(我们只看前7行指令):先executeintx=1;然后我们需要执行tryreturnx;此时并没有真正返回x的值,而是将x的值作为临时存储变量存储在局部变量表中,即保护值。最后输入finally,执行x=2;此时虽然x已经被赋值为2,但是由于刚才的保护操作,真正进行返回操作时,会将保护的暂存变量压入栈并返回。为了更好的理解上面的操作,我们再写一个简单的代码:publicstaticinttest2(){intx=1;尝试{返回x;}最后{x=2;返回x;}}我们想想执行结果是Several?答案是2而不是1。我们看一下程序的字节码指令,通过对比发现第六行中有一行是iload_1,另一行是iload_0。这是什么决定的?原因就是我们上面提到的保护机制。当finally中有return语句时,保护机制就会失效,变量的值会被压入栈中返回。总结return的执行优先级高于finally,但是return语句执行完后,函数不会立即终止,而是将结果保存在栈帧中的局部变量表中,然后再执行中的语句finally块将继续执行;如果finally块中包含return语句,则try块中要返回的值不会被保护,而是直接跳转到finally语句执行,最后在finally语句中返回,在finally中改变返回值blockfinally的值会被执行。细心的朋友应该能发现,上面字节码指令图中第4-7行和第9-12行的字节码指令是完全一致的,那么为什么会出现重复呢?说明书呢?首先我们来分析一下这些重复的指令是干什么的。经过分析,我们发现它们是x=2;returnx;的字节码指令,也就是finally代码块中的代码。因此,我们有理由怀疑,如果在上述代码中加入catch代码块,finally代码块对应的字节码指令也会再次出现。publicstaticinttest2(){intx=1;尝试{返回x;}赶上(异常e){x=3;}最后{x=2;返回x;}}反编译后果然不出所料,repeat字节码指令出现了3次。我们回到最初的问题,为什么finally代码的字节码指令出现了3次?原来,为了保证所有异常路径和正常路径的执行流程都必须执行finally中的代码,finally中的字节码指令在try和catch之后,再加上自己的指令,正好3次。.这也是为什么finally一定会被执行的原因。最后会被处决吗?为什么上面说finally里面的代码肯定会执行,现在还要多做呢?请