<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Jvm 學習——異常處理

    異常表

    每一個try語句塊catch的異常都與異常表中的一項相對應,異常表中的每一項都包括:

    1. 起點
    2. 終點,始終把catch異常位置的pc指針偏移量的最大值大1
    3.  處理異常時跳轉到的字節碼序列中的pc指針偏移量
    4.  catch的異常類的常量池索引

     

    例如:

    public class Test {
        
    public static void main(String[] args) {

            
    try {
                Class.forName(
    "java.lang.String");
            }
     catch (ClassNotFoundException e) {
                e.printStackTrace();
            }


        }

    }

    javap –c查看字節碼如下:

     

    Compiled from "Test.java"
    public class Test extends java.lang.Object{
    public Test();
      Code:
       
    0:    aload_0
       
    1:    invokespecial    #1//Method java/lang/Object."<init>":()V
       4:    return

    public static void main(java.lang.String[]);
      Code:
       
    0:    ldc    #2//String java.lang.String
       2:    invokestatic    #3//Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
       5:    pop    
       
    6:    goto    14
       
    9:    astore_1
       
    10:    aload_1
       
    11:    invokevirtual    #5//Method java/lang/ClassNotFoundException.printStackTrace:()V
       14:    return
      Exception table:
       from   to  target type
         
    0     6     9   Class java/lang/ClassNotFoundException
    }

     

    可見ClassNotFoundException異常可能會在0~6之間拋出,9開始處的代碼處理此異常。

     

    當產生異常的時候,jvm將會在整個異常表中搜索與之匹配的項,如果當前pc在異常表入口所指的范圍內,并且所拋出的異常是此入口所指向的類或者其子類,則跳轉到對應的處理代碼繼續執行。

     

    方法可能會拋出哪些已檢查異常

    Class文件的attribute_info中保存有Exceptions屬性,記錄著每個方法throws的異常信息。具體的可以查看class類文件格式相關的文章。

     

    athrow指令從棧頂彈出Throwable對象引用,拋出異常。

     

    finally語句

    jvm規范中,finally語句是通過jsr/jsr_wret指令實現的。當執行jsr/jsr_w的時候將finally執行完成后的返回地址壓入棧中,進入finally后會馬上將此地址保存到一個局部變量中,執行完成后,ret從此局部變量中取出返回地址。???為什么會先把返回地址保存到局部變量中呢???因為,當從finally語句返回的時候需要將返回地址成棧中彈出,當finally語句非正常結束(break,continue,return, 拋異常)的時候就不用再考慮這個問題。

     

    以下是jvm規范中Compiling finally的一段:

    void tryFinally() {
        
    try {
            tryItOut();
        }
     finally {
            wrapItUp();
        }

    }

    the compiled code is
    Method 
    void tryFinally()
       
    0     aload_0            // Beginning of try block
       1    invokevirtual #6         // Method Example.tryItOut()V
       4     jsr 14            // Call finally block
       7     return            // End of try block
       8     astore_1            // Beginning of handler for any throw
       9     jsr 14            // Call finally block
      12     aload_1            // Push thrown value
      13     athrow            // and rethrow the value to the invoker
      14     astore_2            // Beginning of finally block
      15     aload_0            // Push this
      16     invokevirtual #5         // Method Example.wrapItUp()V
      19     ret 2            // Return from finally block
    Exception table:
           From     To     Target         Type
        
    0        4        8           any

     

    tryItOut排除任何異常后都將會被異常表中的any項捕獲,執行完finally后,會執行athrow指令將異常拋出。

     

    jdk的某一個版本開始就不會編譯出編譯出含jsr/jsr_wret的字節碼了,因為有指令上的缺陷,導致jvm的檢驗和分析系統出現漏洞。

     

    再說finally的非正常退出

    finally中使用breakcontinuereturn、拋出異常等認為是finally的非正常結束。非正常結束的時候,ret指令不會被執行,很可能會出現意想不到的結果。如:

     

    public class Test {
        
    public static boolean test(boolean b) {
            
    while (b) {
                
    try {
                    
    return true;
                }
     finally {
                    
    /*
                    break;                          始終返回false
                    continue;                         javac編譯再java執行會出現死循環
                                                    在eclipse中甚至會出現報錯:提示找到不main class
                    return false;                     始終返回false
                    throw new RuntimeException("");    拋出異常
                     
    */

                }

            }


            
    return false;
        }


        
    public static void main(String[] args) {
            System.out.println(test(
    true));
        }

    }


    建議:在寫finally語句的時候,盡量避免非正常結束!


     

    posted on 2011-05-27 14:39 happyenjoylife 閱讀(2605) 評論(4)  編輯  收藏

    評論

    # re: Jvm 學習——異常處理 2011-05-27 16:46 代孕

    來學習了,謝謝博主的文章了。  回復  更多評論   

    # re: Jvm 學習——異常處理 2011-05-27 22:02 愛課件

    不錯哦  回復  更多評論   

    # re: Jvm 學習——異常處理 2011-06-03 11:35 程先生

    字節碼,看不懂啊,去哪里學習啊?  回復  更多評論   

    # re: Jvm 學習——異常處理 2011-06-11 18:04 happyenjoylife

    @程先生
    字節碼可以看jvm規范,也可以看《深入java虛擬機》,又可以上網找找
      回復  更多評論   


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     

    導航

    <2011年5月>
    24252627282930
    1234567
    891011121314
    15161718192021
    22232425262728
    2930311234

    統計

    常用鏈接

    留言簿

    隨筆檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 一边摸一边爽一边叫床免费视频| 日本中文字幕免费看| 亚洲校园春色另类激情| 人妻无码一区二区三区免费| 亚洲人色婷婷成人网站在线观看 | 精品亚洲永久免费精品| 亚洲中文字幕无码一区 | 色噜噜亚洲男人的天堂| 中国在线观看免费国语版| 久久精品国产亚洲av麻豆图片| 青青免费在线视频| 99久久人妻精品免费一区| 亚洲资源在线视频| aⅴ在线免费观看| 亚洲一线产品二线产品| 国产美女a做受大片免费| 4480yy私人影院亚洲| 91香蕉成人免费网站| 亚洲av永久无码精品网址| 亚洲日韩中文在线精品第一| 亚洲精品中文字幕乱码影院| 国产成人精品免费视频网页大全| 亚洲乱码一二三四区乱码| 国产美女无遮挡免费视频| 三级毛片在线免费观看| 精品国产免费观看久久久| 国产午夜亚洲精品不卡| 国产AV无码专区亚洲AV漫画| 69免费视频大片| 久久亚洲国产午夜精品理论片| 国产成人一区二区三区视频免费| 亚洲一级特黄大片无码毛片| 成人爽a毛片免费| 亚洲欧洲日韩国产一区二区三区| 99精品视频在线免费观看| 中文字幕亚洲情99在线| 在线A亚洲老鸭窝天堂| 国产成人yy免费视频| 成年网在线观看免费观看网址 | 91丁香亚洲综合社区| 亚洲国产精品专区在线观看|