java finally 笔试题_从 Java 字节码角度看 try catch finally 面试题

Java 笔试中,经常会考 try catch finally执行顺序和返回值的问题,大部分都只在书里面看过,说 finally 一定会执行。其背后的原因值得深究,看看 try catch finally 这个语法糖背后的实现原理

try catch 字节码分析

public class TryCatchFinallyDemo {

public void foo() {

try {

tryItOut1();

} catch (MyException1 e) {

handleException(e);

}

}

}

javac TryCatchFinallyDemo.java; javap -c TryCatchFinallyDemo

8fcdb963f58217a1d118ebf3e7567f31.png

在编译后字节码中,每个方法都附带一个异常表(Exception table),异常表里的每一行表示一个异常处理器,由from、to、target、type组成。

其含义是在[from, to]字节码范围内,抛出了异常类型为type的异常,就会跳转到target表示的字节码处。

比如,上面的例子异常表表示:在0到4中间如果抛出了MyException1的异常,就跳转到7执行。

当有多个的catch的情况下,又会是怎样?

public void foo() {

try {

tryItOut2();

} catch (MyException1 e) {

handleException1(e);

} catch (MyException2 e) {

handleException2(e);

}

}

对应字节码如下:

fe6b9b337dad7218a5008dd33b82d32c.png

可以看到多一个异常,会在异常表(Exception table里面多一条记录)。

当程序出现异常时,Java 虚拟机会从上至下遍历异常表中所有的条目。当触发异常的字节码索引值在某个异常条目的[from, to]范围内,则会判断抛出的异常与该条目想捕获的异常是否匹配。

如果匹配,Java 虚拟机会将控制流跳转到 target 指向的字节码。

如果遍历完所有的异常表,还未匹配到异常处理器,那么该异常将蔓延到调用方(caller)中重复上述的操作。最坏的情况下虚拟机需要遍历该线程 Java 栈上所有方法的异常表

finally 字节码分析

finally 的字节码分析最为有意思,之前我一直以为 finally 的实现是用 goto 跳转来实现的(低版本的jdk确实如此),实际上并非如此

public void foo() {

try {

tryItOut1();

} catch (MyException1 e) {

handleException(e);

} finally {

handleFinally();

}

}

9a75a6b5e1125913edcae20166476b98.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值