引子
首先,小編聲明一下,這里講的Exception不僅僅是Exception一個(gè)類,而是異常機(jī)制,就像下面圖中的所有(含繼承Error和Exception的)。
異常類圖
當(dāng)然JDK中更為細(xì)致的異常繼承體系也不是本篇探討內(nèi)容,本次呢,指北君將對(duì)異常在JVM層面的執(zhí)行原理和ARM進(jìn)行介紹,這里ARM也不是芯片架構(gòu),而是指自動(dòng)資源管理。
異常表
要想了解異常執(zhí)行原理,異常表是一個(gè)最佳的入口,異常表是什么?我來看看下面的數(shù)據(jù)結(jié)構(gòu)描述:
exception_table {
u2 start_pc;
u2 end_pc;
u2 handler_pc;
u2 catch_type;
}
它是虛擬機(jī)中用于表述異常處理的一種數(shù)據(jù)結(jié)構(gòu),我再來看異常表的樣例,下面是一段包含try-catch代碼編譯后的字節(jié)碼中的內(nèi)容:
from to target type
8 41 41 Class java/lang/IllegalArgumentException
8 41 41 Class java/io/IOException
8 53 63 any
邏輯上的表述可以用下圖表示:
異常類圖
- 監(jiān)測(cè)從8-41(41不包含)號(hào)指令的IllegalArgumentException
- 監(jiān)測(cè)從8-41指令的IOException
- 監(jiān)測(cè)從8到53指令的結(jié)束動(dòng)作,包含三種情況:跳出指令(比如return指令集);athrow指令且沒有匹配的異常類型;指令執(zhí)行到最后一條
- 如果監(jiān)測(cè)到指定動(dòng)作,則按照異常表進(jìn)行跳轉(zhuǎn)
現(xiàn)在,回到異常表,我們可以看到異常表包含多條異常處理數(shù)據(jù),每條數(shù)據(jù)包含四個(gè)屬性
- from 監(jiān)控的指令集起始編號(hào)
- to 監(jiān)控的指令集結(jié)束編號(hào)
- target 滿足條件后指令跳轉(zhuǎn)目標(biāo)
- 異常匹配的類型,特殊類型any,對(duì)應(yīng)fanally塊,監(jiān)控try塊和catch塊
對(duì)于return,athrow等指令,執(zhí)行順序需要注意,指令是在對(duì)應(yīng)的處理之后執(zhí)行。
可能會(huì)讓你意識(shí)混亂的例子:
public String execOrder(int sn) {
StringBuilder build = new StringBuilder();
try {
build.append("try-block");
if(sn == 0) {
return build.append(", end").toString();
}
}catch(RuntimeException e) {
build.append(", catch-block");
}finally{
build.append(", finally-block");
}
return build.toString();
}
我們之前說過finally塊會(huì)在return之前執(zhí)行,那是不是執(zhí)行結(jié)果是:try->finally->end這種順序呢?實(shí)際的執(zhí)行的結(jié)果是:try-block,end。可以看到,finally塊沒有對(duì)結(jié)果形成影響,當(dāng)然,這并不說它沒執(zhí)行,只是reutrn的結(jié)果在執(zhí)行finally塊時(shí)已經(jīng)計(jì)算出結(jié)果了,在執(zhí)行完finally塊后將之前計(jì)算的結(jié)果返回了而已。所以我們要深入理解了執(zhí)行的原理,才能正確理解結(jié)果。
ARM 自動(dòng)資源管理
講完前面的異常執(zhí)行原理后,指北君現(xiàn)在給大家介紹異常機(jī)制在JDK1.7中一個(gè)優(yōu)化特性:自動(dòng)資源管理。經(jīng)常使用IO的小伙伴一定對(duì)關(guān)閉IO很煩,寫法繁瑣,關(guān)閉前還要做判斷,并且在關(guān)閉塊代碼還要加try-catch,就如同下面類似的代碼:
InputStreamReader in = null;
OutputStreamWriter out = null;
try {
in = new InputStreamReader(new FileInputStream(""));
}catch(IOException e) {
}finally {
try {
if(in != null) {
in.close();
}
if(out != null) {
in.close();
}
}catch(IOException e) {
}
}
反正指北君每次寫這種代碼的時(shí)候很煩,就是那種啥事沒干,占我一塊黃金代碼位置的感覺,對(duì)于有精簡代碼癖好的人來說,就像吃了一口蒼蠅般難受。有了ARM后,我們?cè)賮砜纯葱碌膶懛ǎ?/p>
public void sample2() {
try (InputStreamReader in = new InputStreamReader(new FileInputStream(""))){
in.read();
}catch(IOException e) {
}finally {
}
}
是不是簡潔多了,資源直接在try后的括號(hào)內(nèi)進(jìn)行聲明,而且不需要顯式的關(guān)閉流的代碼,這難道就是ARM!是不是有點(diǎn)小興奮!對(duì)于ARM自動(dòng)資源管理要點(diǎn)如下:
- 在try后的括號(hào)內(nèi)聲明需要自動(dòng)關(guān)閉的資源
- 資源必須實(shí)現(xiàn)一個(gè)關(guān)鍵接口:AutoCloseable。在滿足上面的條件后,JDK將為我們自動(dòng)關(guān)閉資源。當(dāng)然這種寫法即使想手動(dòng)關(guān)閉,在catch和finally部分也拿不到資源引用。
又到了追根溯源環(huán)節(jié)了,自動(dòng)資源管理是如何實(shí)現(xiàn)的呢?先看看class文件有啥變化。
21: aload_3
22: invokevirtual #112 // Method java/io/InputStreamReader.read:()I
25: pop
26: ldc #51 // String try-block
28: astore 4
30: aload_3
31: ifnull 94
34: aload_3
35: invokevirtual #103 // Method java/io/InputStreamReader.close:()V
38: goto 94
41: astore_1
42: aload_3
43: ifnull 50
46: aload_3
47: invokevirtual #103 // Method java/io/InputStreamReader.close:()V
50: aload_1
51: athrow
52: astore_2
對(duì)比之前的字節(jié)碼文件,我們明顯發(fā)現(xiàn)雖然代碼行數(shù)少了,但是Class編譯后的內(nèi)容一點(diǎn)都沒少,而且異常表中除了finally對(duì)應(yīng)的處理,還增加了額外的部分。具體幾個(gè)不同點(diǎn):
- 字節(jié)碼中竟然有close調(diào)用
- 異常表中增加了內(nèi)容
Exception table:
from to target type
21 30 41 any
4 52 52 any
0 74 74 Class java/io/IOException
0 78 85 any
好奇怪的異常表,我們查看指令,可以明顯找出最后一條是對(duì)應(yīng)finally處理。前面的呢?經(jīng)過分析我們發(fā)現(xiàn)前面是finally形式的關(guān)閉資源。看到這里,結(jié)果就很明顯了,自動(dòng)資源管理實(shí)際是上編譯幫助我們做了顯示關(guān)閉的邏輯,在JVM執(zhí)行層面沒有增加新的功能。簡而言之,自動(dòng)資源管理是編譯器層面的改進(jìn),通過擴(kuò)展語法和增強(qiáng)編譯能力(增加自動(dòng)的資源關(guān)閉能力)來實(shí)現(xiàn)自動(dòng)化編碼。
總結(jié)
關(guān)于Java的異常的原理,以及自動(dòng)資源管理的用法和實(shí)現(xiàn)方式,就給大家介紹到這里。
-
芯片
+關(guān)注
關(guān)注
456文章
51154瀏覽量
426268 -
JAVA
+關(guān)注
關(guān)注
19文章
2974瀏覽量
104973 -
代碼
+關(guān)注
關(guān)注
30文章
4823瀏覽量
68899 -
編譯
+關(guān)注
關(guān)注
0文章
661瀏覽量
32974 -
JVM
+關(guān)注
關(guān)注
0文章
158瀏覽量
12252
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論