转载:http://blog.csdn.net/sureyonder/article/details/5560538

Java虚拟机在每个try语句块和与其相关的catch子句的结尾 处都会“调用”finally子句的子例程。实际上,finally子句在方法内部的表现很象“微型子例程”。finally子句正常结束后-指的是finally子句中最后一条语句正常执行完毕,不包括抛出异常,或执行return、continue、break等情况,隶属于这个finally子句的微型子例程执行“返回”操作。程序在第一次调用微型子例程的地方继续执行后面的语句。

finally“微型子例程”不等同于方法函数的调用,finally子句都是在同一个栈内执行的,微型子例程的“返回”操作也不会涉及到方法退栈,仅仅是使程序计数器pc跳转到同一个方法的一个不同的位置继续执行。

一 异常丢失

  1. public static void exceptionLost()
  2. {
  3. try
  4. {
  5. try
  6. {
  7. throw new Exception( "exception in try" );
  8. }
  9. finally
  10. {
  11. throw new Exception( "exception in finally" );
  12. }
  13. }
  14. catch( Exception e )
  15. {
  16. System.out.println( e );
  17. }
  18. }

exceptionLost()的输出结果是“exception in finally”,而不是try块中抛出的异常,这是JAVA异常机制的一个瑕疵-异常丢失。

在字节码中,throw语句不是原子性操作。在较老的JDK中,exceptionLost()中try块的throw语句分解为几步操作:

1) 把Exception("exception in try")对象引用存储到一个局部变量中
  astore_2  // pop the reference to the thrown exception, store into local variable 2
2) 调用finally微型子程序
3) 把局部变量中的Exception("exception in try")对象引用push到操作数栈顶,然后抛出异常
  aload_2  // push the reference to the thrown exception from local variable 2

  athrow   // throw the exception

如果finally通过break、return、continue,或者抛出异常而退出,那么上面的第3步就不会执行。

在JDK1.6中,通过字节码我们可以看到,finally子句作为一种特殊的catch来实现的,下面是exceptionLost()方法的异常表:

Exception table:
  from   to   target  type
   0     10    10     any
 0     21    21     Class java/lang/Exception

finally可以捕获从0行到9行之间抛出的任何类型(any)的异常,并重新抛出捕获的异常,或者抛出一个自己构造的新异常,这个新异常就会覆盖try语句块中的异常。

二 返回值覆盖

  1. public static int getValue()
  2. {
  3. int value = 0;
  4. try
  5. {
  6. value = 100;
  7. return value;
  8. }
  9. finally
  10. {
  11. value = 200;
  12. }
  13. }

这个方法的返回值是100还是200?结果是100。
在字节码中,return语句不是原子性操作,它会把getValue()中的return语句分解为几步操作:
1) 把value值存储到一个局部变量(这里命名为temp)中:
   iload_0   // push local variable 0 - the 100
   istore_2   //  pop an int (the 100), store into local varaible 2
2) 调用finally微型子程序
3) 把局部变量(指temp)的值push到操作数栈顶,然后返回到调用方法
     iload_2  // push local varaible 2 - the 100
   ireturn      // return int on top of the stack - the 100: return 100

由于return语句在返回之前会把返回值保存到一个临时的局部变量中,所以在finally子句内对value重新赋值不会影响返回值。

了解finally子句内在的一些知识,我们能够了解finally能够做什么和不能够做什么,这样会帮助我们正确使用finally子句。

JAVA finally字句的异常丢失和返回值覆盖解析的更多相关文章

  1. Java异常处理场景中不同位置的返回值详细解析

    Java 异常处理中的返回值在不同位置不同场景下是有一些差别的,这里需要格外注意 具体分以下两种场景: 1 finally语句块没有return语句,即当代码执行到try或者catch语句块中的ret ...

  2. JAVA中执行JavaScript代码并获取返回值

    JAVA中执行JavaScript代码并获取返回值 场景描述 实现思路 技术要点 代码实现 测试方法 运行结果 改进空间 场景描述 今天在CSDN上偶然看到一个帖子对于一段字符串 “var p=‘xx ...

  3. Java和Ibatis调用存储过程并取得返回值详解

    Java和Ibatis调用存储过程并取得返回值详解 2011-07-19 17:33 jiandanfeng2 CSDN博客 字号:T | T 本文主要介绍了Java和Ibatis调用存储过程的方法, ...

  4. 为什么阿里巴巴Java开发手册中强制要求接口返回值不允许使用枚举?

    在阅读<阿里巴巴Java开发手册>时,发现有一条关于二方库依赖中接口返回值不允许使用枚举类型的规约,具体内容如下: 在谈论为什么之前先来科普下什么是二方库,二方库也称作二方包,一般指公司内 ...

  5. .net单元测试——常用测试方式(异常模拟、返回值测试、参数测试、数据库访问代码测试)

    最近在看.net单元测试艺术,我也喜欢单元测试,今天介绍一下如何测试异常.如何测试返回值.如何测试模拟对象的参数传递.如何测试数据库访问代码.单元测试框架使用的是NUnit,模拟框架使用的是:Rhin ...

  6. Java中能否利用函数参数来返回值

    转自https://blog.csdn.net/da_da_xiong/article/details/70039532 我们在写代码时通常会遇到一种情况,就是我们可能希望在一个函数操作完成后返回两个 ...

  7. Java反射机制二 获取方法的返回值或参数的泛型信息

    在使用反射机制时,我们经常需要知道方法的参数和返回值类型,很简单  ,下面上示例,示例中的两个方法非常相似 package deadLockThread; import java.lang.refle ...

  8. Java - 关于基础数据类型的形参和返回值

    1. 当基础数据类型被当作形参时,最好使用其包装类,因为这样可方便调用者传参(基础数据类型亦或是其包装类都可)   2. 当基础数据类型被当作返回值时,最好使用原型,因为这样可以方便调用者接收返回值( ...

  9. Java 8新特性--Lambda表达式作为返回值

    lambda表达式作为方法的返回值:

随机推荐

  1. xtrabackup数据库备份

    xtrabackup备份 一.Xtrabackup概述 1.1.简介 Xtrabackup是一个对InnoDB做数据备份的工具,支持在线热备份(备份时不影响数据读写),是商业备份工具InnoDB Ho ...

  2. url语法

    URL的主要部分 URL通常被写成如下形式: <方案>:<方案描述部分> 一个URL包含了它使用的方案名称(<方案>), 其后紧跟一个冒号,然后是一个字符串 (&l ...

  3. 怎样判断iOS App是通过哪种途径启动的?

    http://www.cnblogs.com/daguo/p/3759514.html - (BOOL)application:(UIApplication *)application didFini ...

  4. Android手势识别总结

    一:首先,在Android系统中,每一次手势交互都会依照以下顺序执行. 1. 接触接触屏一刹那,触发一个MotionEvent事件. 2. 该事件被OnTouchListener监听,在其onTouc ...

  5. js/jQuery实现类似百度搜索功能

    一.页面代码:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www. ...

  6. 设置MyEclipse黑色主题背景

    设置MyEclipse黑色主题背景 1. 下载 http://eclipsecolorthemes.org/  看哪个合适直接点击进入, 下载右边的epf 2. 下载完成...打开myeclipse. ...

  7. ftp_get_file_and_directory

    class DirectoryItem { public Uri BaseUri; public string AbsolutePath { get { return string.Format(&q ...

  8. webpack之代码分离

    https://robertknight.github.io/posts/webpack-dll-plugins/ webpack一般会把一个文件里import/require的文件都会打包在一起,最 ...

  9. hive CliDriver 源码分析

    664行 CliDriver main启动 public static void main(String[] args) throws Exception { int ret = new CliDri ...

  10. php中cookie实现二级域名可访问操作的方法

    本文实例讲述了php中cookie实现二级域名可访问操作的方法.分享给大家供大家参考.具体方法如下: cookie在一些应用中很常用,假设我有一个多级域名要求可以同时访问主域名绑定的cookie,下面 ...