try catch finally语句_try catch后面的语句还会执行吗

try catch finally语句_try catch后面的语句还会执行吗查看jvm编译后的字节码,可以清晰的解释这个问题。 该文档给出的示例是基于50.0及之前版本的例子,仅供辅助理解。但是文档中总结了try-catch-finally 流程执行的四种情况: 下面给出java8版本的实践demo,对照编译后的字节码可解释。 该语句会将从catch …

try catch finally语句_try catch后面的语句还会执行吗

try-catch-finally 语句是在各种情况下是如何执行的?

查看jvm编译后的字节码,可以清晰的解释这个问题。

官方规范参考:《The Java® Virtual Machine Specification Java SE 8 Edition》 3.13 Compiling finally

该文档给出的示例是基于50.0及之前版本的例子,仅供辅助理解。但是文档中总结了try-catch-finally 流程执行的四种情况:

  • 语句块内的所有语句正常执行结束
  • 通过 return 语句退出方法
  • 执行 break continue 语句
  • (try block)抛出异常

下面给出java8版本的实践demo,对照编译后的字节码可解释。

java代码:



/**
 * 右键文件 -> externalTools -> javap
 */
public class TestForFinally {
    private int tryBlock;
    private int catchBlock;
    private int finallyBlock;
    private int methodExit;

    /**
     * 语句块内的所有语句正常执行结束
     */
    public void test1() {
        try {
            tryBlock = 0;
        } catch (Exception e) {
            catchBlock = 1;
        } finally {
            finallyBlock = 2;
        }
        methodExit = 3;
    }

    /**
     * 通过 return 语句退出方法
     */
    public void test2(){
        try {
            tryBlock = 0;
            return;
        } catch (Exception e) {
            catchBlock = 1;
        } finally {
            finallyBlock = 2;
        }
        methodExit = 3;
    }

    /**
     * 执行 break continue 语句
     */
    public void test3(){
        for (int i = 0; i < 100; i++) {
            try {
                tryBlock = 0;
            } catch (Exception e) {
                catchBlock = 1;
                break;
            } finally {
                finallyBlock = 2;
            }
        }
        methodExit = 3;
    }

    /**
     * (try block)抛出异常
     */
    public void test4(){
        try {
            tryBlock = 0;
            throw new RuntimeException("throw from try block");
        } catch (Exception e) {
            catchBlock = 1;
        } finally {
            finallyBlock = 2;
        }
        methodExit = 3;
    }
}


字节码:

  public individual.jmy.bytecode.TestForFinally();
    Code:
       0: aload_0
       1: invokespecial #1 // Method java/lang/Object."<init>":()V
       4: return

  public void test1();
    Code:
       0: aload_0
       1: iconst_0
       2: putfield      #2 // Field tryBlock:I
       5: aload_0
       6: iconst_2
       7: putfield      #3 // Field finallyBlock:I
      10: goto          35
      13: astore_1
      14: aload_0
      15: iconst_1
      16: putfield      #5 // Field catchBlock:I
      19: aload_0
      20: iconst_2
      21: putfield      #3 // Field finallyBlock:I
      24: goto          35
      27: astore_2
      28: aload_0
      29: iconst_2
      30: putfield      #3 // Field finallyBlock:I
      33: aload_2
      34: athrow
      35: aload_0
      36: iconst_3
      37: putfield      #6 // Field methodExit:I
      40: return
    Exception table:
       from    to  target type
           0     5    13   Class java/lang/Exception
           0     5    27   any
          13    19    27   any

  public void test2();
    Code:
       0: aload_0
       1: iconst_0
       2: putfield      #2 // Field tryBlock:I
       5: aload_0
       6: iconst_2
       7: putfield      #3 // Field finallyBlock:I
      10: return
      11: astore_1
      12: aload_0
      13: iconst_1
      14: putfield      #5 // Field catchBlock:I
      17: aload_0
      18: iconst_2
      19: putfield      #3 // Field finallyBlock:I
      22: goto          33
      25: astore_2
      26: aload_0
      27: iconst_2
      28: putfield      #3 // Field finallyBlock:I
      31: aload_2
      32: athrow
      33: aload_0
      34: iconst_3
      35: putfield      #6 // Field methodExit:I
      38: return
    Exception table:
       from    to  target type
           0     5    11   Class java/lang/Exception
           0     5    25   any
          11    17    25   any

  public void test3();
    Code:
       0: iconst_0
       1: istore_1
       2: iload_1
       3: bipush        100
       5: if_icmpge     49
       8: aload_0
       9: iconst_0
      10: putfield      #2 // Field tryBlock:I
      13: aload_0
      14: iconst_2
      15: putfield      #3 // Field finallyBlock:I
      18: goto          43
      21: astore_2
      22: aload_0
      23: iconst_1
      24: putfield      #5 // Field catchBlock:I
      27: aload_0
      28: iconst_2
      29: putfield      #3 // Field finallyBlock:I
      32: goto          49
      35: astore_3
      36: aload_0
      37: iconst_2
      38: putfield      #3 // Field finallyBlock:I
      41: aload_3
      42: athrow
      43: iinc          1, 1
      46: goto          2
      49: aload_0
      50: iconst_3
      51: putfield      #6 // Field methodExit:I
      54: return
    Exception table:
       from    to  target type
           8    13    21   Class java/lang/Exception
           8    13    35   any
          21    27    35   any

  public void test4();
    Code:
       0: aload_0
       1: iconst_0
       2: putfield      #2 // Field tryBlock:I
       5: new           #7 // class java/lang/RuntimeException
       8: dup
       9: ldc           #8 // String throw from try block
      11: invokespecial #9 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
      14: athrow
      15: astore_1
      16: aload_0
      17: iconst_1
      18: putfield      #5 // Field catchBlock:I
      21: aload_0
      22: iconst_2
      23: putfield      #3 // Field finallyBlock:I
      26: goto          37
      29: astore_2
      30: aload_0
      31: iconst_2
      32: putfield      #3 // Field finallyBlock:I
      35: aload_2
      36: athrow
      37: aload_0
      38: iconst_3
      39: putfield      #6 // Field methodExit:I
      42: return
    Exception table:
       from    to  target type
           0    15    15   Class java/lang/Exception
           0    21    29   any

需要特别说明的是,有一种情况是catch block抛出异常,参考test1方法对应字节码的异常表,catch block 抛出异常,会跳转到

27: astore_2

该语句会将从catch block 抛出的异常存入局部变量表的index=2中。 并在最后执行:

33: aload_2
34: athrow

该语句从局部变量表中读取index=2的数(即catch block 抛出的异常),并抛出。

由此可见,catch block 如果抛出异常,则该方法向调用方抛出的是catch block产生的异常,如果try block 也产生了异常,则会被覆盖。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13900.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注