最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java虛擬機(jī)處理異常的最佳方式

 更新時(shí)間:2019年03月10日 09:34:34   作者:銀河系技術(shù)博客  
這篇文章主要給大家介紹了關(guān)于Java虛擬機(jī)處理異常的最佳方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

歡迎來到Under The Hood專欄。本專欄旨在讓Java開發(fā)人員一瞥在運(yùn)行Java程序底層的神秘機(jī)制。本月的文章繼續(xù)討論Java虛擬機(jī)的字節(jié)碼指令集,方法是檢查Java虛擬機(jī)處理異常拋出和捕獲的方式,包括相關(guān)的字節(jié)碼。本文不討論finally條款 - 這是下個(gè)月的主題。后續(xù)文章將討論字節(jié)碼系列的其他成員。

下面話不多說了,來一起看看詳細(xì)的介紹吧

Exceptions

Exceptions允許您順利處理程序運(yùn)行時(shí)發(fā)生的意外情況。要演示Java虛擬機(jī)處理異常的方式,請(qǐng)考慮一個(gè)名為NitPickyMath的類。它提供了對(duì)整數(shù)執(zhí)行加法,減法,乘法,除法和余數(shù)的方法。NitPickyMath在溢出,下溢和被零除的條件下拋出已檢查的異常。Java虛擬機(jī)將在整數(shù)除零上拋出一個(gè)ArithmeticException,但不會(huì)在溢出和下溢上拋出任何異常。方法拋出的異常定義如下:

class OverflowException extends Exception {
}
class UnderflowException extends Exception {
}
class DivideByZeroException extends Exception {
}

捕獲和拋出異常的簡(jiǎn)單方法是remainder類的方法NitPickyMath:

static int remainder(int dividend, int divisor)
 throws DivideByZeroException {
 try {
  return dividend % divisor;
 }
 catch (ArithmeticException e) {
  throw new DivideByZeroException();
 }
}

該remainder方法僅在傳遞兩個(gè)int參數(shù)時(shí)執(zhí)行余數(shù)運(yùn)算。如果余數(shù)運(yùn)算的除數(shù)為零,則余數(shù)運(yùn)算拋出一個(gè)ArithmeticException。這個(gè)方法捕獲了這個(gè)ArithmeticException并拋出一個(gè)DivideByZeroException。

DivideByZeroException和ArithmeticException之間的差別是DivideByZeroException是一個(gè)檢查異常,并且ArithmeticException是未經(jīng)檢查。因?yàn)锳rithmeticException是非受檢異常,所以方法不需要在throws子句中聲明此異常,即使它可能會(huì)拋出它。任何屬于Error或者RuntimeException子類的異常都是非受檢異常。(ArithmeticException是RuntimeException的子類。)通過捕獲ArithmeticException然后拋出DivideByZeroException,該remainder方法強(qiáng)制其客戶端處理除零異常的可能性,通過捕獲它或在自己的throws子句中聲明DivideByZeroException。這是因?yàn)橐褭z查的異常,例如DivideByZeroException,拋出方法必須由方法捕獲或在方法的throws子句中聲明。未經(jīng)檢查的異常(例如ArithmeticException,不需要在throws子句中捕獲或聲明)。

javac為該remainder方法生成以下字節(jié)碼序列:

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

該remainder方法的字節(jié)碼序列有兩個(gè)獨(dú)立的部分。第一部分是該方法的正常執(zhí)行路徑。這部分從pc偏移0到3。第二部分是catch子句,它從pc偏移4到12。

主字節(jié)碼序列中的irem指令可能會(huì)拋出一個(gè)ArithmeticException。如果發(fā)生這種情況,Java虛擬機(jī)知道通過查找表中的異常來跳轉(zhuǎn)到實(shí)現(xiàn)catch子句的字節(jié)碼序列。捕獲異常的每個(gè)方法都與一個(gè)異常表相關(guān)聯(lián),該異常表在類文件中與方法的字節(jié)碼序列一起傳遞。每個(gè)try塊捕獲的每個(gè)異常在異常表中都有一個(gè)條目。每個(gè)條目都有四條信息:起點(diǎn)和終點(diǎn),要跳轉(zhuǎn)到的字節(jié)碼序列中的pc偏移量,以及正被捕獲的異常類的常量池索引。remainder類的NitPickyMath方法的異常表如下所示:

Exception table:
   from   to  target type
     0     4     4   <Class java.lang.ArithmeticException>

上面的異常表指示從pc偏移0到3(包括0),表示ArithmeticException將被捕獲的范圍。在標(biāo)簽“to”下面的表中列出的是try塊的端點(diǎn)值,它總是比捕獲異常的最后一個(gè)pc偏移量多一。在這種情況下,端點(diǎn)值列為4,捕獲到異常的最后一個(gè)pc偏移量為3。此范圍(包括0到3)對(duì)應(yīng)于在remainder的try塊內(nèi)實(shí)現(xiàn)代碼的字節(jié)碼序列。如果ArithmeticException在pc偏移量為0和3之間(包括0和3)之間拋出,則表中列出的"to"就是跳轉(zhuǎn)到的pc偏移量。

如果在執(zhí)行方法期間拋出異常,Java虛擬機(jī)將在異常表中搜索匹配的條目。如果當(dāng)前程序計(jì)數(shù)器在條目指定的范圍內(nèi),并且拋出的異常類是由條目指定的異常類(或者是指定異常類的子類),則異常表?xiàng)l目匹配。Java虛擬機(jī)按照條目在表中的顯示順序搜索異常表。找到第一個(gè)匹配項(xiàng)后,Java虛擬機(jī)會(huì)將程序計(jì)數(shù)器設(shè)置為新的pc偏移位置并繼續(xù)執(zhí)行。如果未找到匹配項(xiàng),Java虛擬機(jī)將彈出當(dāng)前堆棧幀并重新拋出相同的異常。當(dāng)Java虛擬機(jī)彈出當(dāng)前堆棧幀時(shí),它有效地中止當(dāng)前方法的執(zhí)行并返回調(diào)用此方法的方法。但是,不是在前一個(gè)方法中繼續(xù)正常執(zhí)行,而是在該方法中拋出相同的異常,這會(huì)導(dǎo)致Java虛擬機(jī)經(jīng)歷搜索該方法的異常表的相同過程。

Java程序員可以使用throw語句拋出異常,例如remainder中的一個(gè)子句catch(ArithmeticException),其中一個(gè) DivideByZeroException創(chuàng)建并拋出。執(zhí)行拋出的字節(jié)碼如下表所示:


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

athrow指令從堆棧中彈出頂部字節(jié),并且會(huì)認(rèn)為它是一個(gè)Throwable子類的引用(或Throwable本身)。拋出的異常是彈出對(duì)象引用定義的類型。

Play Ball!: a Java virtual machine simulation

下面的applet演示了一個(gè)執(zhí)行一系列字節(jié)碼的Java虛擬機(jī)。模擬中的字節(jié)碼序列由javac生成。

類的playBall方法如下所示:

class Ball extends Exception {
}
class Pitcher {
 private static Ball ball = new Ball();
 static void playBall() {
  int i = 0;
  while (true) {
   try {
    if (i % 4 == 3) {
     throw ball;
    }
    ++i;
   }
   catch (Ball b) {
    i = 0;
   }
  }
 }
}

javac為該playBall方法生成的字節(jié)碼如下所示:

0 iconst_0             // Push constant 0
   1 istore_0         // Pop into local var 0: int i = 0;
           // The try block starts here (see exception table, below).
   2 iload_0              // Push local var 0
   3 iconst_4             // Push constant 4
   4 irem                 // Calc remainder of top two operands
   5 iconst_3             // Push constant 3
   6 if_icmpne 13    // Jump if remainder not equal to 3: if (i % 4 == 3) {
                    // Push the static field at constant pool location #5,
                   // which is the Ball exception itching to be thrown
   9 getstatic #5 <Field Pitcher.ball LBall;>
  12 athrow        // Heave it home: throw ball;
  13 iinc 0 1       // Increment the int at local var 0 by 1: ++i;
                    // The try block ends here (see exception table, below).
  16 goto 2               // jump always back to 2: while (true) {}
                          // The following bytecodes implement the catch clause:
  19 pop              // Pop the exception reference because it is unused
  20 iconst_0             // Push constant 0
  21 istore_0             // Pop into local var 0: i = 0;
  22 goto 2            // Jump always back to 2: while (true) {}
Exception table:
   from   to  target type
     2    16    19   <Class Ball>
     ```

該playball方法永遠(yuǎn)循環(huán)。每四次循環(huán),playball拋出Ball并抓住它,只是因?yàn)樗苡腥ぁR驗(yàn)閠ry塊和catch子句都在無限循環(huán)中,所以樂趣永遠(yuǎn)不會(huì)停止。局部變量i從0開始,每次遞增遞增循環(huán)。當(dāng)if語句出現(xiàn)true時(shí),每次i等于3 時(shí)都會(huì)發(fā)生Ball異常,拋出異常。

Java虛擬機(jī)檢查異常表并發(fā)現(xiàn)確實(shí)存在適用的條目。條目的有效范圍是2到15(包括兩者),異常在pc偏移12處拋出。條目捕獲的異常是類Ball,拋出的異常是類Ball。鑒于這種完美匹配,Java虛擬機(jī)將拋出的異常對(duì)象推送到堆棧,并繼續(xù)在pc偏移19處執(zhí)行catch子句,這里僅將int i重置為0,并且循環(huán)重新開始。

要驅(qū)動(dòng)模擬,只需按“步驟”按鈕。每次按下“Step”按鈕都會(huì)使Java虛擬機(jī)執(zhí)行一個(gè)字節(jié)碼指令。要開始模擬,請(qǐng)按“重置”按鈕。要使Java虛擬機(jī)重復(fù)執(zhí)行字節(jié)碼而不需要進(jìn)一步操作,請(qǐng)按“運(yùn)行”按鈕。然后,Java虛擬機(jī)將執(zhí)行字節(jié)碼,直到按下“停止”按鈕。applet底部的文本區(qū)域描述了要執(zhí)行的下一條指令??鞓伏c(diǎn)擊。

英文原文:https://www.javaworld.com/article/2076868/how-the-java-virtual-machine-handles-exceptions.html

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • 分析HashMap 的 JDK 源碼

    分析HashMap 的 JDK 源碼

    這篇文章主要分析了HashMap 的 JDK 源碼,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下
    2020-10-10
  • Spring AI實(shí)現(xiàn)智能聊天模型

    Spring AI實(shí)現(xiàn)智能聊天模型

    通過本文的介紹,我們深入了解了Spring AI項(xiàng)目的優(yōu)勢(shì)和特性,以及在實(shí)際應(yīng)用中的快速實(shí)戰(zhàn)示例,Spring AI作為一個(gè)高度抽象化的人工智能應(yīng)用程序開發(fā)框架,為開發(fā)者提供了便捷的模型支持、靈活的功能模塊交換和優(yōu)化能力
    2024-11-11
  • Java中的常用輸入輸出語句的操作代碼

    Java中的常用輸入輸出語句的操作代碼

    這篇文章主要介紹了Java中的常用輸入輸出語句的操作代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • 深入淺析Java反射機(jī)制

    深入淺析Java反射機(jī)制

    Java反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為Java語言的反射機(jī)制
    2015-11-11
  • Java?多線程并發(fā)ReentrantLock

    Java?多線程并發(fā)ReentrantLock

    這篇文章主要介紹了Java?多線程并發(fā)ReentrantLock,Java?提供了?ReentrantLock?可重入鎖來提供更豐富的能力和靈活性,感興趣的小伙伴可以參考一下
    2022-06-06
  • Java8新特性Stream短路終端操作實(shí)例解析

    Java8新特性Stream短路終端操作實(shí)例解析

    這篇文章主要介紹了Java8新特性Stream短路終端操作實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Java中Boolean和boolean的區(qū)別詳析

    Java中Boolean和boolean的區(qū)別詳析

    boolean是基本數(shù)據(jù)類型Boolean是它的封裝類,和其他類一樣,有屬性有方法,可以new,下面這篇文章主要給大家介紹了關(guān)于Java中Boolean和boolean區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • mybatis Map查詢結(jié)果下劃線轉(zhuǎn)駝峰的實(shí)例

    mybatis Map查詢結(jié)果下劃線轉(zhuǎn)駝峰的實(shí)例

    這篇文章主要介紹了mybatis Map查詢結(jié)果下劃線轉(zhuǎn)駝峰的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • SpringBoot使用@Validated處理校驗(yàn)的方法步驟

    SpringBoot使用@Validated處理校驗(yàn)的方法步驟

    @Validated?注解的主要目的是啟用和利用?Spring?的驗(yàn)證框架,它可以用于類上也可以用于方法參數(shù)上,本文給大家介紹了SpringBoot使用@Validated優(yōu)雅的處理校驗(yàn)的方法步驟,通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2024-08-08
  • mybatis-plus多表查詢操作方法

    mybatis-plus多表查詢操作方法

    這篇文章主要介紹了mybatis-plus多表查詢操作方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-12-12

最新評(píng)論

英超| 孝义市| 晋城| 同仁县| 正安县| 濮阳县| 县级市| 安宁市| 文昌市| 泰顺县| 孙吴县| 息烽县| 新龙县| 黔西县| 南丰县| 子长县| 凤台县| 探索| 漳平市| 略阳县| 高陵县| 潍坊市| 夏津县| 砚山县| 阆中市| 正蓝旗| 东丽区| 民乐县| 邯郸县| 曲靖市| 白山市| 华阴市| 汨罗市| 县级市| 高雄县| 达日县| 荥阳市| 施甸县| 运城市| 闵行区| 监利县|