每一個(gè)try語(yǔ)句塊catch的異常都與異常表中的一項(xiàng)相對(duì)應(yīng),異常表中的每一項(xiàng)都包括:
例如:
用javap –c查看字節(jié)碼如下:
可見ClassNotFoundException異常可能會(huì)在0~6之間拋出,9開始處的代碼處理此異常。
當(dāng)產(chǎn)生異常的時(shí)候,jvm將會(huì)在整個(gè)異常表中搜索與之匹配的項(xiàng),如果當(dāng)前pc在異常表入口所指的范圍內(nèi),并且所拋出的異常是此入口所指向的類或者其子類,則跳轉(zhuǎn)到對(duì)應(yīng)的處理代碼繼續(xù)執(zhí)行。
Class文件的attribute_info中保存有Exceptions屬性,記錄著每個(gè)方法throws的異常信息。具體的可以查看class類文件格式相關(guān)的文章。
athrow指令從棧頂彈出Throwable對(duì)象引用,拋出異常。
在jvm規(guī)范中,finally語(yǔ)句是通過jsr/jsr_w與ret指令實(shí)現(xiàn)的。當(dāng)執(zhí)行jsr/jsr_w的時(shí)候?qū)?/span>finally執(zhí)行完成后的返回地址壓入棧中,進(jìn)入finally后會(huì)馬上將此地址保存到一個(gè)局部變量中,執(zhí)行完成后,ret從此局部變量中取出返回地址。???為什么會(huì)先把返回地址保存到局部變量中呢???因?yàn)椋?dāng)從finally語(yǔ)句返回的時(shí)候需要將返回地址成棧中彈出,當(dāng)finally語(yǔ)句非正常結(jié)束(break,continue,return, 拋異常)的時(shí)候就不用再考慮這個(gè)問題。
以下是jvm規(guī)范中Compiling finally的一段:
當(dāng)tryItOut排除任何異常后都將會(huì)被異常表中的any項(xiàng)捕獲,執(zhí)行完finally后,會(huì)執(zhí)行athrow指令將異常拋出。
從jdk的某一個(gè)版本開始就不會(huì)編譯出編譯出含jsr/jsr_w、ret的字節(jié)碼了,因?yàn)橛兄噶钌系娜毕荩瑢?dǎo)致jvm的檢驗(yàn)和分析系統(tǒng)出現(xiàn)漏洞。
在finally中使用break、continue、return、拋出異常等認(rèn)為是finally的非正常結(jié)束。非正常結(jié)束的時(shí)候,ret指令不會(huì)被執(zhí)行,很可能會(huì)出現(xiàn)意想不到的結(jié)果。如:
建議:在寫finally語(yǔ)句的時(shí)候,盡量避免非正常結(jié)束!
posted on 2011-05-27 14:39 happyenjoylife 閱讀(2596) 評(píng)論(4) 編輯 收藏
來(lái)學(xué)習(xí)了,謝謝博主的文章了。 回復(fù) 更多評(píng)論
不錯(cuò)哦 回復(fù) 更多評(píng)論
字節(jié)碼,看不懂啊,去哪里學(xué)習(xí)啊? 回復(fù) 更多評(píng)論
@程先生字節(jié)碼可以看jvm規(guī)范,也可以看《深入java虛擬機(jī)》,又可以上網(wǎng)找找 回復(fù) 更多評(píng)論