日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

从JVM指令层面看try-catch-finally返回值问题

發布時間:2025/3/21 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从JVM指令层面看try-catch-finally返回值问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

貌似很多人對下面的方法的返回值都比較迷糊:

Java代碼

  • package?cc.lixiaohui.demo;????
  • ????
  • public?class?ReturnValueTest?{????
  • ????public?int?test()?{????
  • ????????int?a;????
  • ????????try?{????
  • ????????????a?=?1;????
  • ????????????//int?b?=?1?/?0;????
  • ????????????return?a;????
  • ????????}?catch?(Exception?e)?{????
  • ????????????a?=?2;????
  • ????????????return?a;????
  • ????????}?finally?{????
  • ????????????a?=?3;????
  • ????????}????
  • ????}????
  • }??
  • ?

    test方法的返回值自然是1,如果把注釋那行去掉,那就是2.

    ?

    為什么?

    用javap -verbose ReturnValueTest 查看字節碼:

    重點查看test()方法指令: 下載

    Javap代碼

  • Compiled?from?"ReturnValueTest.java"??
  • public?class?cc.lixiaohui.demo.ReturnValueTest?extends?java.lang.Object??
  • ??SourceFile:?"ReturnValueTest.java"??
  • ??minor?version:?0??
  • ??major?version:?49???????
  • ??Constant?pool:????????--常量池??
  • const?#1?=?class????????#2;?????//??cc/lixiaohui/demo/ReturnValueTest??
  • const?#2?=?Asciz????????cc/lixiaohui/demo/ReturnValueTest;??
  • const?#3?=?class????????#4;?????//??java/lang/Object??
  • const?#4?=?Asciz????????java/lang/Object;??
  • const?#5?=?Asciz????????<init>;??
  • const?#6?=?Asciz????????()V;??
  • const?#7?=?Asciz????????Code;??
  • const?#8?=?Method???????#3.#9;??//??java/lang/Object."<init>":()V??
  • const?#9?=?NameAndType??#5:#6;//??"<init>":()V??
  • const?#10?=?Asciz???????LineNumberTable;??
  • const?#11?=?Asciz???????LocalVariableTable;??
  • const?#12?=?Asciz???????this;??
  • const?#13?=?Asciz???????Lcc/lixiaohui/demo/ReturnValueTest;;??
  • const?#14?=?Asciz???????test;??
  • const?#15?=?Asciz???????()I;??
  • const?#16?=?class???????#17;????//??java/lang/Exception??
  • const?#17?=?Asciz???????java/lang/Exception;??
  • const?#18?=?Asciz???????a;??
  • const?#19?=?Asciz???????I;??
  • const?#20?=?Asciz???????e;??
  • const?#21?=?Asciz???????Ljava/lang/Exception;;??
  • const?#22?=?Asciz???????SourceFile;??
  • const?#23?=?Asciz???????ReturnValueTest.java;??
  • ??
  • {??
  • public?cc.lixiaohui.demo.ReturnValueTest();?????--構造方法就不分析了??
  • ??Code:??
  • ???Stack=1,?Locals=1,?Args_size=1??
  • ???0:???aload_0??
  • ???1:???invokespecial???#8;?//Method?java/lang/Object."<init>":()V??
  • ???4:???return??
  • ??LineNumberTable:??
  • ???line?8:?0??
  • ??
  • ??LocalVariableTable:??
  • ???Start??Length??Slot??Name???Signature??
  • ???0??????5??????0????this???????Lcc/lixiaohui/demo/ReturnValueTest;??
  • ??
  • ??
  • public?int?test();??
  • ??Code:??
  • ???Stack=1,?Locals=5,?Args_size=1?--?[Stack=1貌似表示棧深度為1(不確定),]Locals=5表示局部變量表長度為5,?Args_size=1表示該方法有1個參數(this)??
  • ???0:???iconst_1????????--將int值?1?壓棧??
  • ???1:???istore_1????????--將棧頂值(即1)彈出保存至局部變量表第2個位置(局部變量表下標是從0開始的,但是0位置被this變量占用了)??
  • ???2:???iload_1?????????--將局部變量表第2個位置的值壓棧??
  • ???3:???istore??4???????--將棧頂的值彈出并保存至局部變量表第5個位置(這里可以看到)??
  • ???5:???iconst_3????????--(這里開始為finally塊)將int值3壓棧??
  • ???6:???istore_1????????--將棧頂的值(即3)彈出并存儲至局部變量表第2個位置??
  • ???7:???iload???4???????--將局部變量表第5個位置(即1)壓棧??
  • ???9:???ireturn?????????--返回棧頂的值(即1),?結束方法調用(該路徑為try(未拋異常)?->?finally)??
  • ?????
  • ???10:??astore_2????????--將棧頂的引用(這里即為catch塊中捕捉到的異常e)存儲至局部變量表的第3個位置??
  • ???11:??iconst_2????????--將int值2壓棧??
  • ???12:??istore_1????????--將棧頂值(即2)彈出并存儲至局部變量表第2個位置??
  • ???13:??iload_1?????????--將局部變量表第2個位置的值(即2)壓棧??
  • ???14:??istore??4???????--將棧頂值彈出(即2)并保存至局部變量表第5個位置,原來第五個位置是1,現在1被覆蓋了,變為2??
  • ???16:??iconst_3????????--(這里開始為finally塊)將int值3壓棧??
  • ???17:??istore_1????????--將棧頂的值(即3)彈出并存儲至局部變量表第2個位置??
  • ???18:??iload???4???????--將局部變量表第5個位置(即2)壓棧??
  • ???20:??ireturn?????????--返回棧頂的值(即2),結束方法調用(該路徑為try(拋Exception或其子類異常)?->?catch?->?finally)??
  • ?????
  • ???21:??astore_3????????--將棧頂的引用(這里為非Exception的子類異常)存儲至局部變量表的第4個位置??
  • ???22:??iconst_3????????--將int值3壓棧??
  • ???23:??istore_1????????--將棧頂值(即3)彈出并存儲至局部變量表第二個位置??
  • ???24:??aload_3?????????--將局部變量表第4個位置(即為異常引用)壓棧??
  • ???25:??athrow??????????--將棧頂的異常拋出(該路徑為try(拋非Exception或其子類異常)?->?finally,?或者try(拋Exception或其子類異常)?->?catch(拋任何異常)?->?finally?)??
  • ??Exception?table:??
  • ???from???to??target?type??
  • ?????0?????5????10???Class?java/lang/Exception??--若執行到0-5行(即在try塊中)拋出java.lang.Exception或其子類則跳轉至第10行執行(即catch塊)??
  • ?????0?????5????21???any????????????????????????--若執行到0-5行(即在try塊中)拋出非java.lang.Exception或其子類則跳轉至第21行執行(即finally塊)??
  • ????10????16????21???any????????????????????????--若執行到10-16行(即在catch塊中)拋出任何異常則跳轉至21行執行(即finally塊)??
  • ??LineNumberTable:??????--這個表為源碼行數與字節碼行數的映射??
  • ???line?13:?0??
  • ???line?14:?2??
  • ???line?19:?5??
  • ???line?14:?7??
  • ???line?15:?10??
  • ???line?16:?11??
  • ???line?17:?13??
  • ???line?19:?16??
  • ???line?17:?18??
  • ???line?18:?21??
  • ???line?19:?22??
  • ???line?20:?24??
  • ??
  • ??LocalVariableTable:???????--這個即為局部變量表,?start和length結合起來就可以確定該變量的作用范圍,?例如this作用范圍為整個方法??
  • ???Start??Length??Slot??Name???Signature??
  • ???0??????26??????0????this???????Lcc/lixiaohui/demo/ReturnValueTest;???--占用第1個slot(一個slot應該是32bits)??
  • ???2??????8??????1????a???????I?????????????????????????????????????????--I標識int,?占用第2個slot??
  • ???13??????8??????1????a???????I????????????????????????????????????????--占用第2個slot??
  • ???24??????2??????1????a???????I????????????????????????????????????????--占用第2個slot??
  • ???11??????10??????2????e???????Ljava/lang/Exception;???????????????????--占用第3個slot??
  • ??
  • ??
  • }??
  • ?

    可以發現jvm始終把返回值放在最后一個局部變量表的位置,而且在finally中改變x并不影響返回值.

    轉載于:https://my.oschina.net/u/2978057/blog/769725

    總結

    以上是生活随笔為你收集整理的从JVM指令层面看try-catch-finally返回值问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。