從字節碼去分析trycathfinal塊

首先我們編寫一段用來測試的代碼

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章