java中的异常和finally

本次文章中所有反汇编所用版本均为1.8

我们都知道finally是不管是否有异常都一定会执行的代码段

他的内部其实是通过调整goto指令跳转的位置来实现的

代码如下

public void testForFinally() {
		try {
			System.out.println(2);
		} finally {
			System.out.println(1);
		}
	}

反汇编如下

stack=2, locals=2, args_size=1
         0: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
         3: iconst_2
         4: invokevirtual #21                 // Method java/io/PrintStream.println:(I)V
         7: goto          20
        10: astore_1
        11: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
        14: iconst_1
        15: invokevirtual #21                 // Method java/io/PrintStream.println:(I)V
        18: aload_1
        19: athrow
        20: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
        23: iconst_1
        24: invokevirtual #21                 // Method java/io/PrintStream.println:(I)V
        27: return

他在调用玩syso后跳转的不是27(如上代码,goto  20),而是跳转到20,执行的是finally的代码

因为变量的生命周期,finally的代码块和try代码块不是一个代码块,所以里面的变量在代码块结束后下一个变量使用时被清空了。

而如果代码没有finally的情况下,是直接跳转到return的

这就是为什么finally一定会执行

异常表

代码如下

public void testForException() {
		try {
			System.out.println(2);
		} catch (NullPointerException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

反汇编如下

stack=2, locals=2, args_size=1
         0: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
         3: iconst_2
         4: invokevirtual #21                 // Method java/io/PrintStream.println:(I)V
         7: goto          23
        10: astore_1
        11: aload_1
        12: invokevirtual #27                 // Method java/lang/NullPointerException.printStackTrace:()V
        15: goto          23
        18: astore_1
        19: aload_1
        20: invokevirtual #32                 // Method java/lang/Exception.printStackTrace:()V
        23: return
      Exception table:
         from    to  target type
             0     7    10   Class java/lang/NullPointerException
             0     7    18   Class java/lang/Exception

这里最下方有一个异常表,表示抓取的行号,target是exception中执行代码的起始地址,exception处理完后是一个goto

如果只有一个异常的时候是没有goto的,exception指令执行完后直接是return

猜你喜欢

转载自blog.csdn.net/a397525088/article/details/81661725