catch后面的代码会执行吗_字节码层面理解try、catch、finally
面試中經常有關于try、catch、finally相關的問題,今天從字節碼層面了解他們的運行流程。
簡單代碼
直接上測試簡單代碼,如下圖:
這里是一個簡單的測試代碼,代碼中有三個異常和一個finally,這里用一個int數組來替代對象,面試中經常會問最終會返回數組(對象)的值是多少?
在這里我們通過jclasslib查看編譯后的字節碼,并找到方法的字節碼指令,如下圖:
右邊被圈中的就是test()方法執行的字節碼指令,字節碼指令較長,接下來一部分一部分的分析。
字節碼指令分析
前面30行之前的指令對應的是try-catch中間的代碼,把fileInputStream與serverSocket初始化出來放到方法的變量表中。
接著30行之后的指令如下圖:
aload_1加載本地變量表中第1項變量(this是第0項,ids是第1項),接著iconst_0、iconst_1分別表示加載int型0、1,iastore表示把第數組第0項設置值為1,最后astore表示把數組存入本地變量表,也就是在執行"ids[0] =1"這一步代碼。
我們看接下來37至40行指令與上一步比較相似,翻譯過來是在執行"ids[0]=5",41行至49行在執行"System.out.println("finally code");"這樣代碼,51行才執行了return;
從上一段分析可以看出,直到finally中的代碼執行完成后才執行了return指令。這樣我們就能回答面試的那個問題了,因為在finally中修改了數組的值!
異常處理
先看看這個方法的異常表,如下圖:
異常表中除了我們代碼中指明的三個異常外,編譯器還自動生成了5個Any類型的異常,用于處理其他不可預期的異常處理。圈中的三列分別表示異常監控的指令開始、結束行以及處理行,也就是在對應的指令行出現異常他們就能處理。
可以看到我們指明的異常監控的是try-catch中的指令,而編譯器生成的則是監控異常處理中的指令。
繼續看字節碼指令,如下圖:
根據異常表我已經圈出了第一個異常處理的指令,從52行開始,astore_2表示將索引存儲到本地變量表中第2項,實際上就是將"FileNotFoundException e"產生的變量e存入,53至56行指令則是將數字2存入數組中,對應代碼"ids[0]=2;",說明在執行第一個catch中的代碼。
后面的指令可以很明顯的看出來又是在執行finally中的代碼,后面的幾個異常基本相似,都是執行自己的catch中的代碼后再次執行finally中代碼,這里就不再一一分析了!
總結
根據以上分析可以看出,finally不管是程序正常執行還是有異常,在字節碼層面都會把finally中的代碼編譯在正常和異常代碼后面,所以有多少個catch,finally代碼就會多編譯多少次,并且return指令都是在finally中的代碼執行完成后才執行!
Java程序員日常學習筆記,如理解有誤歡迎各位交流討論!
總結
以上是生活随笔為你收集整理的catch后面的代码会执行吗_字节码层面理解try、catch、finally的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springboot接入cas单点登录后
- 下一篇: jenkins pipeline pyt