字节码分析finally块对return返回值的影响
直接進入主題。看如下代碼:
public int test(){int i=0;try {i=1;return i;} catch (Exception e) {i=2;return i;}finally{i=3;} }相信有點經驗的程序員一眼就能說出返回的結果為1,但是您真的知道返回的結果為什么為1嗎?下面我們通過分析下當前方法的字節碼,來說明為什么。
查看字節碼命令:javap -verbose class文件
知識點簡單概要:
看如下字節碼需要簡單了解下棧的結構。
棧包括:局部變量表、操作數棧、動態連接、方法出口等。
下面字節碼主要是對操作棧和局變量表的操作。
test方法的字節碼如下:
stack=1, locals=5, args_size=10: iconst_0 將常量0壓入到操作棧頂1: istore_1 將棧頂元素0存儲到局部變量表中的第二個slot中 (slot2=0) i=02: iconst_1 將常量1壓入到操作棧頂3: istore_1 將棧頂元素1存儲到局部變量表中的第二個slot中 (slot2=1) i=14: iload_1 將局部變量中第二個變量 (i=1) 壓入到操作棧頂5: istore 4 將棧頂元素1存儲到局部變量表中的第四個slot中 (slot4=1) 7: iconst_3 將常量3壓入到操作棧頂8: istore_1 將棧頂元素3存儲到局部變量表中的第二個slot中 (slot2=1) i=39: iload 4 將局部變量中第四個變量 (slot4=1) 壓入到操作棧頂11: ireturn 返回操作棧頂值,這時操作棧中棧頂值為1。12: astore_2 將棧頂元素(e)存儲到局部變量表的第三個slot中13: iconst_2 將常量2壓入到操作棧頂14: istore_1 將棧頂元素2存儲到局部變量表中的第二個slot中 (slot2=2) i=215: iload_1 將局部變量中第二個變量 (i=2) 壓入到操作棧頂16: istore 4 將棧頂元素2存儲到局部變量表中的第四個slot中 (slot4=2) 18: iconst_3 將常量3壓入到操作棧頂19: istore_1 將棧頂元素3存儲到局部變量表中的第二個slot中 (slot2=1) i=320: iload 4 將局部變量中第四個變量 (slot4=2) 壓入到操作棧頂22: ireturn 返回操作棧頂值,這時操作棧中棧頂值為2。23: astore_3 將棧頂元素(其它異常,Exception之外的)存儲到局部變量表的第四個slot中24: iconst_3 將常量3壓入到操作棧頂25: istore_1 將棧頂元素3存儲到局部變量表中的第二個slot中 (slot2=3) i=326: aload_3 將局部變量中第四個變量 (其它異常) 壓入到操作棧頂27: athrow 拋出棧頂元素(異常信息) 無返回值stack=1, locals=5, args_size=1
- stack=1:操作棧的深度
- locals=5:局部變量表中5個slot(槽位),每個slot存儲能一個變量(long、double 需要兩個slot存儲)
1. this變量
2. i 變量
3. e 變量(Exception)
4. Exception之外異常的變量
5. 臨時存儲變量(返回值從臨時存儲中返回的)
- args_size=1: 方法的參數個數(該方法無參數,為什么這里args_size為1呢?因為這個是實例方法,不是靜態方法,他默認會傳過來當前實例的引用,也就是this變量)
字節碼執行路徑
通過字節碼我們發現在編譯成class文件的時候,已經把三種執行路徑都寫到class文件中了。
1. 第一種路徑
第【1-11】行,程序正常執行順序(無異常)
2. 第二種路徑
第【12-22】行,程序報Exception的異常
3. 第三種路徑
第【23-27】行,程序報Exception之外的異常
字節碼大白話解釋說明
第[0-1]行,代碼:int i=0; 第[2-3]行,try塊中代碼:i=1; 第[4-5]行,遇到return時,把 i 的值臨時存儲起來,然后執行finally中的代碼。 第[7-8] 行,finally塊代碼:i=3 第[9-11] 行,執行return語句,把臨時存儲的 i 值返回。(執行finally代碼對返回值無影響) 第[12]行,catch塊代碼: (Exception e) 第[13-14]行,catch塊代碼: i=2 第[15-16]行,遇到catch塊中的return時,把 i 的值臨時存儲起來,然后執行finally中的代碼。 第[18-19]行,finally塊代碼:i=3 第[20-22]行,執行catch塊中return語句,把臨時存儲的 i 值返回。(執行finally代碼對返回值無影響) 第[23]行,局部變量表中存儲Exception之外的異常 第[24-25]行,finally塊代碼:i=3 第[26-27]行,將Exception之外的異常壓入棧頂,并拋出(無返回值)結論
通過字節碼,我們發現,在try語句的return塊中,return 返回的變量并不是直接返回 i 值,而是在執行finally塊之前把i值存儲在臨時區域,當執行return時直接返回的臨時區域中的值,即使在finally語句中把變量 i 的值修改了,也不會影響返回的值。
本人簡書blog地址:http://www.jianshu.com/u/1f0067e24ff8????
點擊這里快速進入簡書
總結
以上是生活随笔為你收集整理的字节码分析finally块对return返回值的影响的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 更改环境变量JAVA_HOME无效
- 下一篇: JVM基于栈的解释器执行原理