首先我們編寫一段用來測試的代碼
public int test(){
try {
System.out.println(1);
} catch (Exception e) {
System.out.println(2);
} finally {
System.out.println(3);
}
return 4;
}
這段代碼包括了trycatchfinally三個部分,首先我們分析一下他的執行步驟
進入這個棧幀後會先執行sout1
之後會執行sout3
如果在println時出現io異常則先執行sout1在執行sou2在執行sou3
下面我們通過verbose查看一下助記符形式的字節碼文件
我將一些不必要的刪除掉了只留下方法的code部分
stack=2, locals=3, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: iconst_1
4: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
7: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
10: iconst_3
11: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
14: goto 45
17: astore_1
18: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
21: iconst_2
22: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
25: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
28: iconst_3
29: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
32: goto 45
35: astore_2
36: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
39: iconst_3
40: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
43: aload_2
44: athrow
45: iconst_4
46: ireturn
從上面的助記符我們可以看出來jvm將我們的條件語句編譯爲了三種情況,並將他們完全編譯出來,並不是一種動態的判斷而是一種靜態的代碼形式。通過goto方法來跳過一些代碼。
這三種情況是
1.執行sout沒有捕捉到異常去執行finally
2.執行sout打印信息後捕捉到異常執行catch和finally
3.執行sout沒有打印就出現異常執行catch和finally
可以看出來finally的代碼塊是被寫在了三個部分而不是一個finally