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

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

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

    廉頗老矣,尚能飯否

    java:從技術到管理

    常用鏈接

    統計

    最新評論

    JVM對Java異常的處理原理【轉載】

    最初我們用 Java 寫 JSP 的時候,幾乎可以不觸及異常,因為 Servlet 容器會把 API 拋出的異常包裝成 ServletException 丟給容器去處理。再后來應用分層,代碼中要處理的異常便多了,一般會轉換成自定義的業務異常類,用 try-catch-throw customerException-finally。再到如今各種框架日臻成熟,代碼中顯式的異常處理又漸漸少了些,借助于 AOP 橫行,異常對業務的影響描述被移入到了配置文件中了,例如,事物處理、權限的控制等。

    這頗有些像手機的發展,當通信技術不甚發達的時候,手里抓的是磚頭,信號是模擬的。后來慢慢瘦身成兩三根手指大小,甚至是就一支筆似的,可如今信息量大了,屏幕要大,再配上 QWERT 鍵盤,機身自然就肥碩了。

    當然與手機的個頭變遷略有不同的是,任憑你怎么對待 Java 中異常,切入 AOP 也好,在 JVM 中處理異常的內在機制始終未變。

    說到 Java 異常,無外乎就是 try、catch、finally、throw、throws 這么幾個關鍵字,這些個的用法是沒必要在這里講了。我們這里主要關鍵一下 catch 和 finally 是如何在編譯后的 class 字節碼中的。

    異常的拋出與捕獲,Catch 子句的表現,來看看一段 Java 代碼及生成的相應字節碼指令。

    1. package com.unmi;   
    2.   
    3. import java.io.UnsupportedEncodingException;   
    4.   
    5. public class AboutCatch {   
    6.        
    7.     public static void main(String[] args){   
    8.         try {   
    9.             transfer("JVM 對 Java 異常的處理","gbk");   
    10.         } catch (Exception e) {   
    11.             //e.printStackTrace();   
    12.         }   
    13.     }   
    14.        
    15.     //字符集轉換的方法   
    16.     public static void transfer(String src, String charset)   
    17.             throws Exception{   
    18.         String result = "";   
    19.         try{   
    20.             //這行代碼可能會拋出空指針,不支持的字符集,數組越界的異常   
    21.             result = new String(src.getBytes(),0,10,charset);   
    22.         }catch(NullPointerException ne){   
    23.             System.out.println("捕獲到異常 ArithemticExcetipn");   
    24.             throw ne;   
    25.         }catch(UnsupportedEncodingException uee){   
    26.             System.out.println("捕獲到異常 UnsupportedEncodingException");   
    27.             throw uee;   
    28.         }catch(Exception ex){ //比如數組越界時在這里可捕獲到   
    29.             System.out.println("捕獲到異常 Exception");   
    30.             throw ex;   
    31.         }   
    32.         System.out.println(result);   
    33.     }   
    34. }   


    來看看上面代碼中的 transfer() 方法相應的字節碼指令,編譯器是 Eclipse 3.3.2 的,它所用的 JDK 是 1.6.0_06,編譯兼容級別設置為 6.0。用命令 javap -c com.unmi.AboutCatch 在 Dos 窗口中就能輸出:

    public static void transfer(java.lang.String, java.lang.String)   throws java.lang.Exception;
      Code:
       0:   ldc     #30; //String
       2:   astore_2
       3:   new     #32; //class java/lang/String
       6:   dup
       7:   aload_0
       8:   invokevirtual   #34; //Method java/lang/String.getBytes:()[B
       11:  iconst_0
       12:  bipush  10
       14:  aload_1
       15:  invokespecial   #38; //Method java/lang/String."<init>":([BIILjava/lang/String;)V
       18:  astore_2
       19:  goto    55  //依據異常表執行完異常處理塊后,再回到這里,然后 goto 到 55 號指令繼續執行
       22:  astore_3
       23:  getstatic       #41; //Field java/lang/System.out:Ljava/io/PrintStream;
       26:  ldc     #47; //String 捕獲到異常 ArithemticExcetipn
       28:  invokevirtual   #49; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       31:  aload_3
       32:  athrow    //拋出 ArthemticException 異常
       33:  astore_3
       34:  getstatic       #41; //Field java/lang/System.out:Ljava/io/PrintStream;
       37:  ldc     #55; //String 捕獲到異常 UnsupportedEncodingException
       39:  invokevirtual   #49; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       42:  aload_3
       43:  athrow    //拋出 UnsupportedEncodingException 異常
       44:  astore_3
       45:  getstatic       #41; //Field java/lang/System.out:Ljava/io/PrintStream;
       48:  ldc     #57; //String 捕獲到異常 Exception
       50:  invokevirtual   #49; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       53:  aload_3
       54:  athrow   //拋出 Exception 異常
       55:  getstatic       #41; //Field java/lang/System.out:Ljava/io/PrintStream;
       58:  aload_2
       59:  invokevirtual   #49; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       62:  return
      Exception table:  //這下面是一個異常表,所以異常不像普通代碼那樣是靠 goto 語句來跳轉的
       from   to  target type
         //0-19 號指令中,碰到 NullPointerException時,跳到 22 號指令
         3    19    22   Class java/lang/NullPointerException

     

         //0-19 號指令中,碰到 UnsupportedEncodingException 時,跳到 33 號指令 
         3    19    33   Class java/io/UnsupportedEncodingException

         //0-19 號指令中,碰到 NullPointerException時,跳到 44 號指令
         3    19    44   Class java/lang/Exception

    說明:

    對于上面的程序,我們可以用下面代碼來調用看看輸出

    1) transfer("JVM 對 Java 異常的處理","gbk");  //正常
    2) transfer(null, "gbk");                                         //空指針異常
    3) transfer("JVM 對","gbk");                               //數組越界異常
    4) transfer("JVM 對","gbk-1");                            //不支持的字符集異常

    最后可以把代碼中的
    catch(Exception ex){ //比如數組越界時在這里可捕獲到
       System.out.println("捕獲到異常 Exception");
       throw ex;
      }

    或是 main() 方法寫成

     public static void main(String[] args) throws Exception{
      transfer("JVM 對 Java 異常的處理","gbk");
     }

    來試試,異常一直未得到處理對 JVM 的影響

    字節碼中,紅色部分是我加上去的注釋,著重描了要關注的地方,其他的出入棧、方法調用的指令可不予以理會,關鍵是只要知曉有一個異常表的存在,try 的范圍就是體現在異常表行記錄的起點和終點。JVM 在 try 住的代碼區間內如有異常拋出的話,就會在當前棧楨的異常表中,找到匹配類型的異常記錄的入口指令號,然后跳到該指令處執行。異常指令塊執行完后,再回來繼續執行后面的代碼。JVM 按照每個入口在表中出現的順序進行檢索,如果沒有發現匹配的項,JVM 將當前棧幀從棧中彈出,再次拋出同樣的異常。當 JVM 彈出當前棧幀時,JVM 馬上終止當前方法的執行,并且返回到調用本方法的方法中,但是并非繼續正常執行該方法,而是在該方法中拋出同樣的異常,這就使得 JVM 在該方法中再次執行同樣的搜尋異常表的操作。

    上面那樣的內層方法無法處理異常的層層向外拋,層層壓棧,這樣就形成一個異常棧。異常棧十分有利于我們透析問題之所在,例如 e.printStackTrace(); 或者帶參數的 e.printStackTrace(); 方法可將異常棧信息定向輸出到他處,還有 log4j 的 log.error(Throwable) 也有此功效。若是在行徑的哪層有能力處理該異常則已,否則直至 JVM,直接造成 JVM 崩潰掉。例如當 main() 方法也把異常拋了出去,JVM 此刻也就到了生命的盡頭。



    柳德才
    13691193654
    18942949207
    QQ:422157370
    liudecai_zan@126.com
    湖北-武漢-江夏-廟山

    posted on 2009-04-08 16:07 liudecai_zan@126.com 閱讀(895) 評論(0)  編輯  收藏 所屬分類: 程序人生

    主站蜘蛛池模板: 亚洲综合久久1区2区3区| 国产成人高清亚洲| 亚洲国产成人久久| 免费人成在线观看网站品爱网 | 亚洲av高清在线观看一区二区| 中中文字幕亚洲无线码| 无码一区二区三区AV免费| 亚洲免费二区三区| 国产精品免费视频播放器| 国产成人综合亚洲| 国产成人99久久亚洲综合精品| 久久久久久国产a免费观看不卡| 亚洲中文字幕不卡无码| 最新亚洲成av人免费看| 亚洲AV无码国产精品色午友在线| 在线免费观看亚洲| 最新国产精品亚洲| 亚洲国产成人久久综合区| a毛片在线还看免费网站| 亚洲综合激情视频| 在线免费观看一级毛片| 色婷婷精品免费视频| 亚洲一区二区三区自拍公司| 24小时免费看片| 99亚洲乱人伦aⅴ精品| 中文字幕亚洲激情| 最近中文字幕mv免费高清在线 | 国产成人va亚洲电影| 亚洲日韩精品一区二区三区 | 成人女人A级毛片免费软件| 亚洲第一成年网站视频| 亚洲一级片内射网站在线观看| 外国成人网在线观看免费视频| 亚洲国产精品综合久久20| 免费国产高清视频| 污污网站免费观看| 亚洲av日韩精品久久久久久a| 亚洲日韩中文字幕在线播放| 黄页网站免费观看| 男人天堂免费视频| 亚洲色大网站WWW永久网站|