l

2013年11月15日 星期五

Java的try、catch、finally(4):Suppressed Exception

Nov. 07 16:23~17:45

image

圖片來源在此。打房有像Java SE 7 打壓exception那麼厲害就好了挑眉質疑

 

被打壓的例外

上一集提到在Java SE 7之後,可以用try-with-resource的方式讓JVM自動幫忙執行cleanup的工作。現在的問題是:如果JVM執行cleanup發生例外,這些cleanup例外要怎麼處理?Java SE 7的作法是,在Throwable類別身上多了一個Throwable[] getSuppressed() method,Suppressed是壓抑、抑制、打壓的意思。顧名思義,getSuppressed() method就是傳回「被抑制的例外」,也就是發生在執行cleanup動作所產生的例外。

請看以下程式片段,首先看到MyOutputStream類別,為了讓JVM可以自動關閉MyOutputStream所使用的資源,它實作了AutoCloseable介面。實作close() method的程式碼直接丟出一個IOException。

螢幕快照 2013-11-07 下午4.40.33

 

接著來使用用try-with-resources的方式來使用MyOutputStream類別。

螢幕快照 2013-11-15 下午3.03.17

 

在main()裡面來測試一下這個Java7TryWithResource() method,呼叫這個方法一定會產生一個IOException,從下列測試可以看出來捕捉到的IOException是由Java7TryWithResource()所丟出來的,還是MyOutputStream的close() method所丟出來的例外。

螢幕快照 2013-11-15 下午3.02.14

 

請參考下圖,答案揭曉,捕捉到的例外是由Java7TryWithResource() method所丟出來的那個IOException。MyOutputStream的close() method所丟出來的IOException變成了suppressed exception。

螢幕快照 2013-11-15 下午3.02.48

***

橋歸橋,路歸路(理論上)

這下子語意就比較清楚了,如果try-with-resources丟出例外,這個例外代表著function failure,如果例外還附帶有suppressed exception,則表示cleanup 失敗(廣義的來講,suppressed exception並不一定都表示cleanup 失敗)。捕捉到例外的人,除了要處理function failure,如果也想處理suppressed exception,則可以呼叫getSuppressed() method來逐一讀出每一個suppressed exception。

現在還剩下一個問題:如果try block或是catch block沒有丟出例外,而只有JVM在執行cleanup發生多的例外,那麼這些例外是由誰來壓制誰?也就是說呼叫者最後會收到哪一個例外?請參考下列程式片段:MyOutputStream、MyConnection、MyInputStream的close() method分別會丟出IOException、SQLException、FileNotFoundException。

螢幕快照 2013-11-15 下午3.05.42

 

在main()裡面測試一下Java7TryWithResources() method。

螢幕快照 2013-11-15 下午3.04.29

 

結果發現,被丟出來的例外是FileNotFoundException,而suppressed exception則是SQLException與IOException。也就是說,看起來JVM是依據使用資源的順序,反向的釋放這些資源(把資源物件依據宣告的順序,逐一放入堆疊之中,最後要執行cleanup動作再從堆疊裡面逐一拿出物件,並且呼叫這些物件的close() methods)。

螢幕快照 2013-11-15 下午3.05.06

***

細心一點的鄉民,看到這裡應該會發現一個問題:有了suppressed exception之後,雖然try block與catch block所丟出來的例外不會被cleanup例外給蓋台,但是例外的語意對捕捉到例外的人來講還是不夠清楚。如上圖所示,一個有suppressed exception的例外,可能是捕抓到try block或是catch block所丟出的例外,也可能是多個cleanup例外所組成。

怎麼辦?這算是一個例外類別設計的問題。下一集再來談一下這個問題。

***

友藏內心獨白:仔細讀,會讀出一點心得滴。

沒有留言:

張貼留言