从字节码看 finally关键字、异常表
大家好,我是烤鴨:
? ? 今天說下?finally 這個關鍵字。
1.??認識finally
finally 總是跟 try、catch一起出現,finally是執行方法結束一定要執行的代碼,比如流關閉等等。
finally是如何實現在異常捕捉之后保證執行 finally 代碼塊里的內容。
其實不管是普通的代碼,還是 try、catch ,JVM都是根據字節碼文件中的指令來執行,
也就是 finally的時候,字節碼指令覆蓋了這一種情況。
而異常之后的操作指令是有專門的異常表來存儲,在字節碼指令之后(不是一定存在的,如果代碼顯示的try catch的話會有),結構如下圖(圖來自《深入理解java虛擬機》)
2.? 代碼實踐
我們看一下 下面的代碼,其實代碼特別簡單,輸出3或4或者拋出非Exception的異常(finally會先執行)。
public class TestCatchFinally {public static void main(String[] args) throws Throwable{int x = 0;try {x = 1;// throw new Throwable();} catch (Exception e) {x = 2;} finally {try {x = 3;} catch (Exception e) {x = 4;}}System.out.println(x);} }看一下生成的字節碼指令
javap -verbose TestCatchFinally.class Classfile / ... 無關內容省略 Constant pool:// 常量池內容省略 {public src.bytecode.TestCatchFinally();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 10: 0LocalVariableTable:Start Length Slot Name Signature0 5 0 this Lsrc/bytecode/TestCatchFinally;public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=5, args_size=10: iconst_01: istore_12: iconst_13: istore_14: iconst_35: istore_16: goto 419: astore_210: iconst_411: istore_112: goto 4115: astore_216: iconst_217: istore_118: iconst_319: istore_120: goto 4123: astore_224: iconst_425: istore_126: goto 4129: astore_330: iconst_331: istore_132: goto 3935: astore 437: iconst_438: istore_139: aload_340: athrow41: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;44: iload_145: invokevirtual #4 // Method java/io/PrintStream.println:(I)V48: returnException table:from to target type4 6 9 Class java/lang/Exception2 4 15 Class java/lang/Exception18 20 23 Class java/lang/Exception2 4 29 any15 18 29 any30 32 35 Class java/lang/Exception// ,,, } SourceFile: "TestCatchFinally.java"字節碼指令比較簡單了,沒什么可說的,我們看下異常表。
第1行指的是字節碼指令 4-6行,對應的代碼內容是 try {x = 3;}catch (Exception e) {x = 4;}。如果觸發了這個異常,就會執行 9行指令,變量賦值為 4。
第2行指的是字節碼指令 2-4行,對應的代碼內容是 try {x = 1;}catch (Exception e) {x = 2;}。如果觸發了這個異常,就會執行 15行指令,變量賦值為 2。
第3行指的是字節碼指令 18-20行,對應的代碼內容是 try {x = 3;}catch (Exception e) {x = 4;}。如果觸發了這個異常,就會執行 23行指令,變量賦值為 4。
關于指令重復,比如 iconst_3 執行了三次,第一次 是正常執行后執行 finally內容,第二次是 異常后執行finally內容,第三次是遇到 非 Exception異常 執行的finally
兩個any 指的是 catch不到的異常,比如 throwable ,如果觸發,程序會執行finally后退出。
3.? 總結
字節碼指令已經把顯示異常和 finally 代碼塊都包含了,剩下的只是按指令執行而已了。
總結
以上是生活随笔為你收集整理的从字节码看 finally关键字、异常表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 运算符和类型转换
- 下一篇: jedate选择一年范围日期插件