try-catch-finally 和 return 是怎么执行的?

沙海 2021年4月18日05:55:18Java评论31字数 3430阅读11分26秒阅读模式
摘要

速读摘要

速读摘要文章源自JAVA秀-https://www.javaxiu.com/13132.html

是位于0到4字节之间的命令抛出了任何类型(any type)的异常,会跳转到11字节处继续运行。astore_1会把抛出的异常对象保存到local variable数组的第二个元素。如果try块中有return statement,一定是finally中的代码先执行,然后return。如果catch block中有return statement,那么也一定是在finally block之后执行。文章源自JAVA秀-https://www.javaxiu.com/13132.html

原文约 1550 | 图片 3 | 建议阅读 4 分钟 | 评价反馈文章源自JAVA秀-https://www.javaxiu.com/13132.html

try-catch-finally 和 return 是怎么执行的?

点击关注 ? 小哈学Java 文章源自JAVA秀-https://www.javaxiu.com/13132.html

点击上方蓝色“小哈学Java”,选择“设为星标”回复“资源”获取独家整理的学习资料!

来源:http://liangfei.me/文章源自JAVA秀-https://www.javaxiu.com/13132.html

最近一直在看Java虚拟机规范,发现直接分析bytecode更能加深对Java语言的理解。文章源自JAVA秀-https://www.javaxiu.com/13132.html

之前看过一篇关于 returnfinally 执行顺序的文章,仅在 Java 的语言层面做了分析,其实我倒觉得直接看 bytecode 可能来的更清晰一点。文章源自JAVA秀-https://www.javaxiu.com/13132.html

先看一个只有 try-finally,没有 catch 的例子。文章源自JAVA秀-https://www.javaxiu.com/13132.html

try - finally文章源自JAVA秀-https://www.javaxiu.com/13132.html

public class ExceptionTest {  public void tryFinally() {    try {      tryItOut();    } finally {      wrapItUp();    }  }  // auxiliary methods  public void tryItOut() { }  public void wrapItUp() {}}

通过 javap -c ExceptionTest 来查看它的字节码。文章源自JAVA秀-https://www.javaxiu.com/13132.html

public void tryFinally();  Code:     0: aload_0     1: invokevirtual #2  // Method tryItOut:()V     4: aload_0     5: invokevirtual #3  // Method wrapItUp:()V     8: goto          18    11: astore_1    12: aload_0    13: invokevirtual #3  // Method wrapItUp:()V    16: aload_1    17: athrow    18: return  Exception table:     from    to  target type         0     4    11   any

如果没有抛出异常,那么它的执行顺序为文章源自JAVA秀-https://www.javaxiu.com/13132.html

0: aload_01: invokevirtual #2  // Method tryItOut:()V4: aload_05: invokevirtual #3  // Method wrapItUp:()V18: return

如果抛出了异常,JVM 会在文章源自JAVA秀-https://www.javaxiu.com/13132.html

Exception table:   from    to  target type       0     4    11   any

中进行控制跳转。如果是位于0到4字节之间的命令抛出了任何类型(any type)的异常,会跳转到11字节处继续运行。文章源自JAVA秀-https://www.javaxiu.com/13132.html

11: astore_112: aload_013: invokevirtual #316: aload_117: athrow

astore_1会把抛出的异常对象保存到local variable数组的第二个元素。下面两行指令用来调用成员方法wrapItUp。文章源自JAVA秀-https://www.javaxiu.com/13132.html

12: aload_013: invokevirtual #3

最后通过文章源自JAVA秀-https://www.javaxiu.com/13132.html

16: aload_117: athrow

重新抛出异常。文章源自JAVA秀-https://www.javaxiu.com/13132.html

通过以上分析可以得出结论:文章源自JAVA秀-https://www.javaxiu.com/13132.html

在try-finally中,try块中抛出的异常会首先保存在local variable中,然后执行finally块,执行完毕后重新抛出异常。文章源自JAVA秀-https://www.javaxiu.com/13132.html

如果我们把代码修改一下,在try块中直接return。文章源自JAVA秀-https://www.javaxiu.com/13132.html

try - return - finally文章源自JAVA秀-https://www.javaxiu.com/13132.html

public void tryFinally() {  try {    tryItOut();    return;  } finally {    wrapItUp();  }}

”反汇编“一下:文章源自JAVA秀-https://www.javaxiu.com/13132.html

 0: aload_0 1: invokevirtual #2 // Method tryItOut:()V 4: aload_0 5: invokevirtual #3 // Method wrapItUp:()V 8: return 9: astore_110: aload_011: invokevirtual #3 // Method wrapItUp:()V14: aload_115: athrow

可以看出finally块的代码仍然被放到了return之前。文章源自JAVA秀-https://www.javaxiu.com/13132.html

如果try块中有return statement,一定是finally中的代码先执行,然后return。文章源自JAVA秀-https://www.javaxiu.com/13132.html

JVM规范是这么说的:文章源自JAVA秀-https://www.javaxiu.com/13132.html

Compilation of a try-finally statement is similar to that of try-catch. Pior to transferring control outside thetry statement, whether that transfer is normal or abrupt, because an exception has been thrown, thefinally clause must first be execute. try - catch - finally文章源自JAVA秀-https://www.javaxiu.com/13132.html

给上面的代码加一个catch块文章源自JAVA秀-https://www.javaxiu.com/13132.html

public void tryCatchFinally() {  try {    tryItOut();  } catch (TestExc e) {    handleExc(e);  } finally {    wrapItUp();  }}

javap一下文章源自JAVA秀-https://www.javaxiu.com/13132.html

public void tryCatchFinally();  Code:     0: aload_0     1: invokevirtual #2     4: aload_0     5: invokevirtual #3     8: goto          31    11: astore_1    12: aload_0    13: aload_1    14: invokevirtual #5                      17: aload_0    18: invokevirtual #3    21: goto          31    24: astore_2    25: aload_0    26: invokevirtual #3    29: aload_2    30: athrow    31: returnException table:   from    to  target type       0     4    11   Class TestExc       0     4    24   any      11    17    24   any

通过Exception table可以看出:文章源自JAVA秀-https://www.javaxiu.com/13132.html

  • catch监听 0 ~ 4 字节类型为TextExc的异常。文章源自JAVA秀-https://www.javaxiu.com/13132.html

  • finally为 0 ~ 4 以及 11 ~ 17 字节任何类型的异常。文章源自JAVA秀-https://www.javaxiu.com/13132.html

也就说 catch block 本身也在 finally block 的管辖范围之内。文章源自JAVA秀-https://www.javaxiu.com/13132.html

如果catch block 中有 return statement,那么也一定是在 finally block 之后执行。文章源自JAVA秀-https://www.javaxiu.com/13132.html

1. 在 SpringBoot 项目中,Spring Security 和 Shiro 该如何选择?2. 万长文字 | 16张图解开AbstractQueuedSynchronizer3. IntelliJ IDEA 2021.1正式发布!快来看看又有哪些神仙功能加入!4. SQL 窗口函数是什么?涨见识了!最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。文章源自JAVA秀-https://www.javaxiu.com/13132.html

谢谢支持哟 (*^__^*)文章源自JAVA秀-https://www.javaxiu.com/13132.html

继续阅读
速蛙云 - 极致体验,强烈推荐!!!购买套餐就免费送各大视频网站会员!快速稳定、独家福利社、流媒体稳定解锁!速度快,全球上网、视频、游戏加速、独立IP均支持!基础套餐性价比很高!这里不多说,我一直正在使用,推荐购买:https://www.javaxiu.com/59919.html
weinxin
资源分享QQ群
本站是JAVA秀团队的技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
沙海
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定