2014-01-10 36 views
1

雖然使用java.nio.channels.Selector對象,但我不禁注意到工廠創建方法Selector.open()拋出IOException。Java NIO Selector.open()IOException

除了成爲處理另一個IOException的痛苦之外,我不明白打開選擇器可能是一個I/O操作,更不用說在某處失敗並拋出IOException。

Selector類,打開裏面的代碼如下:

public static Selector open() throws IOException { 
    return SelectorProvider.provider().openSelector(); 
} 

提的是,它推遲到SelectorProvider對象我去看看代碼openSelector()。如下:

public abstract AbstractSelector openSelector() 
    throws IOException; 

貌似類被在運行時這使甚至更神祕這些選擇器是如何被構造動態加載。

如果「動態加載」失敗,則負責創建選擇器的類是sun.nio.ch.DefaultSelectorProvider,我沒有它的源代碼,所以即使我能跟蹤IOException的來源。

Java的關於選擇器的javadoc不會在所有幫助他們只是狀態:

拋出:IOException - 如果發生I/O錯誤

如果任何人有關於創造了這個集市IOException異常任何見解通過Selector.open()請讓我知道。另外回答一個更實際的問題,如果IOException被「正確」處理(例如messagebox,閃爍的燈光,工具包的嗶聲等)或者只是隱藏在日誌/空的catch塊中。

回答

3

簡單的答案是它是平臺和具體實現,所以你幾乎別無選擇;你應該抓住它並處理它。由於這將是一個非常罕見的事件(之後你將不會有一個Selector),這可能是一個鐘聲和口哨的事情。選項B是忽略它,讓它擊中堆棧的頂部,並停止的東西。

長的答案是,在Linux上,使用當前的默認實現,它不會拋出。如果它大於2.6內核,則openSelector()將實例化並返回EPollSelectorImpl。如果它是< 2.6,你會得到一個PollSelectorImpl。這兩個類的構造函數都不會拋出IOException

但是在Windows上,您將獲得WindowsSelectorImpl,其構造函數確實是 throw IOException。我不得不深入瞭解發生了什麼會導致它,但顯然有些東西可以。

雖然如此,它是一個實現細節,所以它在將來可能會一直改變。

您可以拉出openjdk的完整源代碼來查看這些類的源代碼。

+0

感謝您的信息。如果隨意將任意異常連接起來,他們應該給出一些理由。執行特定與否,並說這種方法可能在發生I/O錯誤時拋出IOException不夠好。無論如何,我懶得拉這個源代碼。如果您確實發現了任何問題,請使用此信息更新您的答案。如果沒有其他人提供新的信息,我會在一段時間後接受。 – initramfs

2

它允許實現拋出IOExceptions,原因很自然不會在API級別指定。例如,Selector的Windows實現使用內部節點爲管道的選擇樹來處理可選通道數超過Windows最大值的情況。所以選擇器必須能夠打開一個管道,這可能會失敗。

+0

似乎每個人都在爲此指責Windows實施。我知道這超出了這個問題,但是你知道任何可能拋出這種異常的其他實現嗎?我會適當地處理它,但肯定會看到如何在其他實現上設置選擇器通道。 – initramfs

+0

我不是'任何責任的Windows實施'。不管它是什麼,實現都會在創建選擇器時發生錯誤,無論在平臺上意味着什麼,所以它必須能夠拋出異常,所以設計者在邏輯上選擇了IOException。 – EJP