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

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

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

    LetsCoding.cn

    天地之間有桿秤,拿秤砣砸老百姓。

    JVM中的異常處理

    歡迎來到“Under The Hood”第六期。本期我們介紹JVM處理異常的方式,包括如何拋出和捕獲異常及相關的字節碼指令。但本文不會討論finally子句,這是下期的主題。你可能需要閱讀往期的文章才能更好的理解本文。

    異常處理

    在程序運行時,異常讓你可以平滑的處理意外狀況。為了演示JVM處理異常的方式,考慮NitPickyMath類,它提供對整數進行加,減,乘,除以及取余的操作。

    NitPickyMath提供的這些操作和Java語言的“+”,“-”,“*”,“/”和“%”是一樣的,除了NitPickyMath中的方法在以下情況下會拋出檢查型(checked)異常:上溢出,下溢出以及被0除。0做除數時,JVM會拋出ArithmeticException異常,但是上溢出和下溢出不會引發任何異常。NitPickyMath中拋出異常的方法定義如下:

    1. class OverflowException extends Exception {
    2. }
    3. class UnderflowException extends Exception {
    4. }
    5. class DivideByZeroException extends Exception {
    6. }

    NitPickyMath類中的remainder()方法就是一個拋出和捕獲異常的簡單方法。

    1. static int remainder(int dividend, int divisor)
    2.     throws DivideByZeroException {
    3.     try {
    4.         return dividend % divisor;
    5.     }
    6.     catch (ArithmeticException e) {
    7.         throw new DivideByZeroException();
    8.     }
    9. }

    remainder()方法,只是簡單的對當作參數傳遞進來的2個整數進行取余操作。如果取余操作的除數是0,會引發ArithmeticException異常。remainder()方法捕獲這個異常,并重新拋出DivideByZeroException異常。

    DivideByZeroException和ArithmeticException的區別是,DivideByZeroException是檢查型(checked)異常,而ArithmeticException是非檢查(unchecked)型異常。由于ArithmeticException是非檢查型異常,一個方法就算會拋出該異常,也不必在其throw子句中聲明它。任何Error或RuntimeException異常的子類異常都是非檢查型異常。(ArithmeticException就是RuntimeException的子類。)通過捕獲ArithmeticException和拋出DivideByZeroException,remainder()方法強迫它的調用者去處理除數為0的可能性,要么捕獲它,要么在其throw子句中聲明DivideByZeroException異常。這是因為,像DivideByZeroException這種在方法中拋出的檢查型異常,要么在方法中捕獲,要么在其throw子句中聲明,二者必選其一。而像ArithmeticException這種非檢查型異常,就不需要去顯式捕獲和聲明。

    javac為remainder()方法生成的字節碼序列如下:

    1. // The main bytecode sequence for remainder:
    2. 0 iload_0               // Push local variable 0 (arg passed as divisor)
    3. 1 iload_1               // Push local variable 1 (arg passed as dividend)
    4. 2 irem                  // Pop divisor, pop dividend, push remainder
    5. 3 ireturn               // Return int on top of stack (the remainder)
    6. // The bytecode sequence for the catch (ArithmeticException) clause:
    7. 4 pop                   // Pop the reference to the ArithmeticException
    8.                         // because it is not used by this catch clause.
    9. 5 new #5 < Class DivideByZeroException >
    10.                         // Create and push reference to new object of class
    11.                         // DivideByZeroException.
    12. 8 dup                   // Duplicate the reference to the new
    13.                         // object on the top of the stack because it
    14.                         // must be both initialized
    15.                         // and thrown. The initialization will consume
    16.                         // the copy of the reference created by the dup.
    17. 9 invokenonvirtual #9 < Method DivideByZeroException.< init >()V >
    18.                         // Call the constructor for the DivideByZeroException
    19.                         // to initialize it. This instruction
    20.                         // will pop the top reference to the object.
    21. 12 athrow               // Pop the reference to a Throwable object, in this
    22.                         // case the DivideByZeroException,
    23.                         // and throw the exception.

    remainder()方法的字節碼有2個單獨的部分。第一部分是該方法的正常執行路徑,這部分從第0行開始,到第3行結束。第二部分是從第4行開始,到12行結束的catch子句。

    主字節碼序列中的irem指令可能會拋出ArithmeticException異常。如果異常發生了,JVM通過在異常表中查找匹配的異常,它會知道要跳轉到相應的異常處理的catch子句的字節碼序列部分。每個捕獲異常的方法,都跟類文件中與方法字節碼一起交付的異常表關聯。每一個捕獲異常的try塊,都是異常表中的一行。每行4條信息:開始行號(from)和結束行號(to),要跳轉的字節碼序列行號(target),被捕獲的異常類的常量池索引(type)。remainder()方法的異常表如下所示:

    FROM
    TO
    TARGET
    TYPE
    0 4 4 < Class java.lang.ArithmeticException >

    上面的異常表表明,行號1到3范圍內,ArithmeticException將被捕獲。異常表中的“to”下面的結束行號始終比異常捕獲的最大行號大1,上表中,結束行號為4,而異常捕獲的最大行號是3。行號0到3的字節碼序列對應remainder()方法中的try塊。“target”列中,是行0到3的字節碼發生ArithmeticException異常時要跳轉到的目標行號。

    如果方法執行過程中產生了異常,JVM會在異常表中查找匹配行。異常表中的匹配行要符合下面的條件:當前pc寄存器的值要在該行的表示范圍之內,[from, to),且產生的異常是該行所指定的異常類或其子類。JVM按從上到下的次序查找異常表。當找到了第一個匹配行,JVM把pc寄存器設為新的跳轉行號,從此行繼續往下執行。如果找不到匹配行,JVM彈出當前棧幀,并重新拋出同一個異常。當JVM彈出當前棧幀時,它會終止當前方法的執行,返回到調用該方法的上一個方法那里。這時,在上一個方法里,并不會繼續正常的執行過程,而是拋出同樣的異常,促使JVM重新查找該方法的異常表。

    Java程序員可以用throw語句拋出像remainder()方法的catch子句中的異常,DivideByZeroException。下表列出了拋出異常的字節碼:

    OPCODE
    OPERAND(S)
    DESCRIPTION
    athrow (none) pops Throwable object reference, throws the exception

    athrow指令把棧頂元素彈出,該元素必須是Throwable的子類或其自身的對象引用,而拋出的異常類型由棧頂彈出的對象引用所指明。

    本文譯自:How the Java virtual machine handles exceptions

    本文出自:碼農合作社 》JVM中的異常處理,轉載請注明。

    posted on 2014-06-02 03:54 Rolandz 閱讀(2764) 評論(0)  編輯  收藏 所屬分類: 編程實踐

    導航

    統計

    留言簿(1)

    隨筆分類(12)

    隨筆檔案(19)

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 免费很黄无遮挡的视频毛片| 91福利免费视频| 日日夜夜精品免费视频| 67194在线午夜亚洲| 成人免费AA片在线观看| 亚洲1234区乱码| 美女无遮挡拍拍拍免费视频| 免费做爰猛烈吃奶摸视频在线观看| 久久久无码精品亚洲日韩软件| 亚洲人成电影在线观看青青| 成人免费大片免费观看网站| 亚洲色WWW成人永久网址| 亚洲丁香婷婷综合久久| 四虎影视www四虎免费| 久久亚洲精品人成综合网| 日韩精品内射视频免费观看| 亚洲视频在线精品| 亚洲AV无码一区二区三区久久精品 | 卡一卡二卡三在线入口免费| 亚洲AV无码AV日韩AV网站| 免费一级毛片清高播放| 中文毛片无遮挡高清免费| 免费看国产一级片| 亚洲欧美国产国产一区二区三区| 亚洲美女免费视频| 亚洲大片在线观看| 日本三级2019在线观看免费| 国产亚洲精品仙踪林在线播放| 扒开双腿猛进入爽爽免费视频| 黄色免费在线观看网址| 亚洲av综合av一区| 国产福利免费视频| 亚洲伊人久久大香线蕉苏妲己| 国产美女在线精品免费观看| 一级一级毛片免费播放| 波多野结衣中文一区二区免费 | 亚洲精品无码久久久久YW| 国产亚洲精品国看不卡| 中文毛片无遮挡高潮免费| 国产精品亚洲综合| 亚洲成a人不卡在线观看|