用bytecode来看try-catch-finally和return
之前看过一篇关于return和finally运行顺序的文章。仅在Java的语言层面做了分析。事实上我倒认为直接看bytecode可能来的更清晰一点。
近期一直在看Java虚拟机规范。发现直接分析bytecode更能加深对Java语言的理解。
先看一个仅仅有try-finally。没有catch的样例。
try - finally
public class ExceptionTest {
public void tryFinally() {
try {
tryItOut();
} finally {
wrapItUp();
}
}
// auxiliary methods
public void tryItOut() { }
public void wrapItUp() {}
}
通过javap -c ExceptionTest来查看它的字节码。
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
假设没有抛出异常,那么它的运行顺序为
0: aload_0
1: invokevirtual #2 // Method tryItOut:()V
4: aload_0
5: invokevirtual #3 // Method wrapItUp:()V
18: return
假设抛出了异常,JVM会在
Exception table:
from to target type
0 4 11 any
中进行控制跳转。假设是位于0到4字节之间的命令抛出了不论什么类型(any type)的异常,会跳转到11字节处继续执行。
11: astore_1
12: aload_0
13: invokevirtual #3
16: aload_1
17: athrow
astore_1会把抛出的异常对象保存到local variable数组的第二个元素。
以下两行指令用来调用成员方法wrapItUp。
12: aload_0
13: invokevirtual #3
最后通过
16: aload_1
17: athrow
又一次抛出异常。
通过以上分析能够得出结论
在try-finally中,try块中抛出的异常会首先保存在local variable中。然后运行finally块,运行完成后又一次抛出异常。
假设我们把代码改动一下。在try块中直接return。
try - return - finally
public void tryFinally() {
try {
tryItOut();
return;
} finally {
wrapItUp();
}
}
”反汇编“一下:
0: aload_0
1: invokevirtual #2 // Method tryItOut:()V
4: aload_0
5: invokevirtual #3 // Method wrapItUp:()V
8: return
9: astore_1
10: aload_0
11: invokevirtual #3 // Method wrapItUp:()V
14: aload_1
15: athrow
能够看出finally块的代码仍然被放到了return之前。
假设try块中有
return statement。一定是finally中的代码先运行,然后return。
JVM规范是这么说的
Compilation of a try-finally statement is similar to that of try-catch. Pior to transferring control outside the
try statement, whether that transfer is normal or abrupt, because an exception has been thrown, the
finally clause must first be execute.
try - catch - finally
给上面的代码加一个catch块
public void tryCatchFinally() {
try {
tryItOut();
} catch (TestExc e) {
handleExc(e);
} finally {
wrapItUp();
}
}
javap一下
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: return
Exception table:
from to target type
0 4 11 Class TestExc
0 4 24 any
11 17 24 any
通过Exception table能够看出:
- catch监听 0 ~ 4 字节类型为
TextExc的异常。 - finally为 0 ~ 4 以及 11 ~ 17 字节不论什么类型的异常。
也就说 catch block 本身也在 finally block 的管辖范围之内。假设
catch block 中有 return statement,那么也一定是在
finally block 之后运行。
查看原文 http://www.liangfeizc.com/blog/article/32/
用bytecode来看try-catch-finally和return的更多相关文章
- java中 try catch finally和return联合使用时,代码执行顺序的小细节
代码1测试 public static void main(String[] args) { aa(); } static int aa() { try { int a=4/0; } catch (E ...
- try catch finally 和return
结论:1.不管有木有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...
- try catch finally中return的执行顺序
下面说一下try{ } catch{}中有return的情况 究竟是哪个return起作用的 话不多说 上代码 1 try中有return的情况 //普通方法 public static int hh ...
- Java的finally语句在try或catch中的return语句执行之后还是之前?
import java.util.HashMap; import java.util.Map; public class FinallyDemo1 { public static void main( ...
- try catch 语句中有return 的各类情况
在牛客上做java题时遇到过多到关于try catch语句的问题,看了很多答案解析,在这里记录一下. 首先给出一道题目: 下面代码的运行结果为? A.catch语句块 和是43 B.编译异常 C.fi ...
- try catch中的return与finally
try catch中的return与finally 代码为 public class Test{ public int add(int a,int b){ try { return a+b; } ca ...
- try,catch,finally含return时的执行顺序及丢失的伪例
最近面试遇到一个之前也看到过但没去看一下的问题.就是有return情况下的try,catch,finally的执行顺序. 今天写了下. 先看顺序问题.总结如下: 一:finally中没有写return ...
- try,catch,finally与return
package com.zl.test; // try catch finally 内有returnpublic class Demo { public static void main(String ...
- 关于try...catch...finally中return的疑惑
原文:http://www.cnblogs.com/and_he/archive/2012/04/17/2453703.html 关于try...catch...finally里面的return一直是 ...
随机推荐
- Problem E: Erratic Ants
这个题没过……!题意:小蚂蚁向四周走,让你在他走过的路中寻找最短路,其中可以反向主要思路:建立想对应的图,寻找最短路径,其中错了好多次,到最后时间没过(1.没有考录反向2.没有考虑走过的路要标记……! ...
- SDUTOJ 1489 求二叉树的先序遍历
<img src="http://img.blog.csdn.net/20141014212549703?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi ...
- MVC3和MVC4中CRUD操作
MVC3中EF实现的CRUD操作 public class HomeController : Controller { // // GET: /Home/ CarModelContainer db = ...
- mysql5.6 主从配置
参考网址:http://www.cnblogs.com/zhoujie/p/mysql1.html http://kerry.blog.51cto.com/172631/277414/ 1.配置主库: ...
- 同事的Excel中的图片突然不能选择
今天上午,同事突然说自己用的Excel不能编辑了,发来一看原来是其中做的图片不能编辑,鼠标放上去后显示个圆圈选不中. 在“视图”中调出“控件工具箱”工具栏,上面有一个三角板与直尺样子的按钮叫“设计模式 ...
- Android 系统搜索框(有浏览记录)
实现Android 系统搜索框(有浏览记录),先看下效果: 一.配置搜索描述文件 要在res中的xml文件加创建sreachable.xml,内容如下: <?xml version=" ...
- C文件操作的语言fgets()
谈fgets(..)功能. 原型 char * fgets(char * s, int n,FILE *stream); 參数: s: 字符型指针.指向存 ...
- Delphi使用StrToDatetime在不同操作系统出现不同的情况(控制面板的时间格式都记录在注册表里,因此也可修改注册表)
Str:= '2010-4-13 06:22:22'; StrToDateTime(Str); 现象:在WinXP, Win2003 都不会报错 但是在Windows7,Windows Serve ...
- Oracle百问百答(一)
Oracle百问百答(一) 01.如何查看oracle的版本信息? 02.如何查看系统被锁的事务信息? 03.怎么获取有哪些用户在使用数据库? 04. 数据表中的字段最大数是多少? 表或视图中的最大列 ...
- 在iPhoneApp中加载PDF
原文: http://ios.biomsoft.com/2012/02/17/load-a-pdf-file-in-the-iphone-app-smoothly/ 本节将学习如何从服务器加载 pdf ...