本篇文章為大家展示了如何在Java虛擬機中處理異常,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
創(chuàng)新互聯(lián)是專業(yè)的馬鞍山網(wǎng)站建設公司,馬鞍山接單;提供網(wǎng)站建設、網(wǎng)站制作,網(wǎng)頁設計,網(wǎng)站設計,建網(wǎng)站,PHP網(wǎng)站建設等專業(yè)做網(wǎng)站服務;采用PHP框架,可快速的進行馬鞍山網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!
Exceptions
Exceptions允許您順利處理程序運行時發(fā)生的意外情況。要演示Java虛擬機處理異常的方式,請考慮一個名為NitPickyMath的類。它提供了對整數(shù)執(zhí)行加法,減法,乘法,除法和余數(shù)的方法。NitPickyMath在溢出,下溢和被零除的條件下拋出已檢查的異常。Java虛擬機將在整數(shù)除零上拋出一個ArithmeticException,但不會在溢出和下溢上拋出任何異常。方法拋出的異常定義如下:
class OverflowException extends Exception { } class UnderflowException extends Exception { } class DivideByZeroException extends Exception { }
捕獲和拋出異常的簡單方法是remainder類的方法NitPickyMath:
static int remainder(int dividend, int divisor) throws DivideByZeroException { try { return dividend % divisor; } catch (ArithmeticException e) { throw new DivideByZeroException(); } }
該remainder方法僅在傳遞兩個int參數(shù)時執(zhí)行余數(shù)運算。如果余數(shù)運算的除數(shù)為零,則余數(shù)運算拋出一個ArithmeticException。這個方法捕獲了這個ArithmeticException并拋出一個DivideByZeroException。
DivideByZeroException和ArithmeticException之間的差別是DivideByZeroException是一個檢查異常,并且ArithmeticException是未經(jīng)檢查。因為ArithmeticException是非受檢異常,所以方法不需要在throws子句中聲明此異常,即使它可能會拋出它。任何屬于Error或者RuntimeException子類的異常都是非受檢異常。(ArithmeticException是RuntimeException的子類。)通過捕獲ArithmeticException然后拋出DivideByZeroException,該remainder方法強制其客戶端處理除零異常的可能性,通過捕獲它或在自己的throws子句中聲明DivideByZeroException。這是因為已檢查的異常,例如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é)碼序列有兩個獨立的部分。第一部分是該方法的正常執(zhí)行路徑。這部分從pc偏移0到3。第二部分是catch子句,它從pc偏移4到12。
主字節(jié)碼序列中的irem指令可能會拋出一個ArithmeticException。如果發(fā)生這種情況,Java虛擬機知道通過查找表中的異常來跳轉(zhuǎn)到實現(xiàn)catch子句的字節(jié)碼序列。捕獲異常的每個方法都與一個異常表相關(guān)聯(lián),該異常表在類文件中與方法的字節(jié)碼序列一起傳遞。每個try塊捕獲的每個異常在異常表中都有一個條目。每個條目都有四條信息:起點和終點,要跳轉(zhuǎn)到的字節(jié)碼序列中的pc偏移量,以及正被捕獲的異常類的常量池索引。remainder類的NitPickyMath方法的異常表如下所示:
Exception table:
from to target type
0 4 4 <Class java.lang.ArithmeticException>
上面的異常表指示從pc偏移0到3(包括0),表示ArithmeticException將被捕獲的范圍。在標簽“to”下面的表中列出的是try塊的端點值,它總是比捕獲異常的最后一個pc偏移量多一。在這種情況下,端點值列為4,捕獲到異常的最后一個pc偏移量為3。此范圍(包括0到3)對應于在remainder的try塊內(nèi)實現(xiàn)代碼的字節(jié)碼序列。如果ArithmeticException在pc偏移量為0和3之間(包括0和3)之間拋出,則表中列出的"to"就是跳轉(zhuǎn)到的pc偏移量。
如果在執(zhí)行方法期間拋出異常,Java虛擬機將在異常表中搜索匹配的條目。如果當前程序計數(shù)器在條目指定的范圍內(nèi),并且拋出的異常類是由條目指定的異常類(或者是指定異常類的子類),則異常表條目匹配。Java虛擬機按照條目在表中的顯示順序搜索異常表。找到第一個匹配項后,Java虛擬機會將程序計數(shù)器設置為新的pc偏移位置并繼續(xù)執(zhí)行。如果未找到匹配項,Java虛擬機將彈出當前堆棧幀并重新拋出相同的異常。當Java虛擬機彈出當前堆棧幀時,它有效地中止當前方法的執(zhí)行并返回調(diào)用此方法的方法。但是,不是在前一個方法中繼續(xù)正常執(zhí)行,而是在該方法中拋出相同的異常,這會導致Java虛擬機經(jīng)歷搜索該方法的異常表的相同過程。
Java程序員可以使用throw語句拋出異常,例如remainder中的一個子句catch(ArithmeticException),其中一個 DivideByZeroException創(chuàng)建并拋出。執(zhí)行拋出的字節(jié)碼如下表所示:
OPCODE | OPERAND(S) | DESCRIPTION |
---|---|---|
athrow | (none) | pops Throwable object reference, throws the exception |
athrow指令從堆棧中彈出頂部字節(jié),并且會認為它是一個Throwable子類的引用(或Throwable本身)。拋出的異常是彈出對象引用定義的類型。
Play Ball!: a Java virtual machine simulation
下面的applet演示了一個執(zhí)行一系列字節(jié)碼的Java虛擬機。模擬中的字節(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>
```
上述內(nèi)容就是如何在Java虛擬機中處理異常,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
當前標題:如何在Java虛擬機中處理異常
地址分享:http://www.rwnh.cn/article26/jippcg.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、網(wǎng)站設計、電子商務、網(wǎng)頁設計公司、網(wǎng)站排名、外貿(mào)網(wǎng)站建設
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)