[英]Java process on Mac OSX does not release socket
我經常遇到一個奇怪的問題(實際上經常)。
我正在運行一個服務器應用程序,它為自己綁定一個套接字。
但有一段時間,套接字沒有被釋放。 雖然Eclipse報告Terminate失敗,但是它會從'ps'和JConsole / JVisualVM中正確消失,但是該過程終止了。 'lsof'也不再為港口顯示任何內容。 但是,當我嘗試再次啟動服務器到同一端口時,我收到此錯誤:
Caused by: java.net.BindException: Address already in use
at sun.nio.ch.Net.bind(Native Method)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:126)
at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:59)
這個問題在我的單元測試中是最糟糕的,它永遠不會完全運行,因為這肯定會在其中一個測試(所有重新創建服務器)之后發生。
我正在運行MacOSX 10.7.3
Java(TM)SE運行時環境(版本1.6.0_31-b04-415-11M3635)Java HotSpot(TM)64位服務器VM(版本20.6-b01-415,混合模式)
我也有Parallels,而且問題看起來似乎是由Parallels網絡適配器引起的,但我不確定它是否與此問題有任何關系(我已經聯系了他們的支持,目前為止沒有任何幫助)。
唯一有助於解決這種情況的是重啟OSX。
有任何想法嗎?
-
這是打開套接字的相關代碼:
channel = (ServerSocketChannel) ServerSocketChannel.open().configureBlocking(false);
channel.socket().bind( addr, 0 );
它被關閉了
channel.close();
但我認為這個過程在這里被卡住了,然后Eclipse殺了它。
-
netstat -an(對於端口6007):
tcp4 73 0 127.0.0.1.6007 127.0.0.1.51549 ESTABLISHED
tcp4 0 0 127.0.0.1.51549 127.0.0.1.6007 ESTABLISHED
tcp4 73 0 127.0.0.1.6007 127.0.0.1.51544 CLOSE_WAIT
tcp4 0 0 127.0.0.1.6007 127.0.0.1.51543 CLOSE_WAIT
tcp4 0 0 10.37.129.2.6007 *.* LISTEN
tcp4 0 0 10.211.55.2.6007 *.* LISTEN
tcp4 0 0 127.0.0.1.6007 *.* LISTEN
tcp4 0 0 10.50.100.236.6007 *.* LISTEN
-
現在,在為每個測試打開套接字后,我得到此異常(此情況下的netstat輸出):
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.net.SocketInputStream.read(SocketInputStream.java:182)
-
從eclipse停止進程我得到了“終止失敗”,但是lsof -i TCP:6007什么也沒顯示,'ps'找不到進程。 netstat輸出沒有變化......
我可以以某種方式殺死套接字而不重新啟動(這有助於一點點)?
-
更新5.5.12:
我現在在Eclipse調試器中運行測試。 這次測試在18種方法后被卡住了。 它被困在15分鍾后停止了主線程。 這是堆棧:
Thread [main] (Suspended)
FileDispatcher.preClose0(FileDescriptor) line: not available [native method]
SocketDispatcher.preClose(FileDescriptor) line: 41
ServerSocketChannelImpl.implCloseSelectableChannel() line: 208 [local variables unavailable]
ServerSocketChannelImpl(AbstractSelectableChannel).implCloseChannel() line: 201
ServerSocketChannelImpl(AbstractInterruptibleChannel).close() line: 97
...
-
嗯,畢竟看起來這個過程並沒有被殺死 - 並且也不會死於殺死-9(我注意到過程712,可能還有710是TestNG進程):
$ kill -9 712
$ ps xa | grep java
700 ?? ?E 0:00.00 (java)
712 ?? ?E 0:00.00 (java)
797 s005 S+ 0:00.00 grep java
- 編輯:10.5.12:
?上面的ps輸出中的E表示該進程正在退出。 我找不到任何方法可以在不重新啟動的情況下完全殺死這樣一個進程。 其他一些應用程序也注意到了同樣的問題。 找不到解決方案:
嘗試在每次測試之后用http://docs.oracle.com/javase/1.4.2/docs/api/java/net/ServerSocket.html#close ()關閉套接字,如果你還沒有。
在這里只是一個黑暗的鏡頭,但要確保等待Selector.select()的任何線程已被喚醒,並已退出。
所以問題似乎在於JDK 6的Mac版本中Selector的實現。安裝新的Oracle JDK 7u4修復了這個問題,與Selector的使用方式無關。
我也有Parallels,而且問題通常是由Parallels網絡適配器引起的......
如果這個問題沒有在其他平台上出現,我會說這是一個公平的賭注。 你做了什么來將Parallels排除在罪魁禍首之外?
如果您認為資源未正確發布,您可以嘗試在shutdownhook中執行發布。 這樣至少在關閉資源時會釋放(盡管如果你很難殺死)
一個非常基本的shutdownhook的例子:
public void shutDownProceedure(){
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
/* my shutdown code here */
}
});
}
這有助於我釋放以前不完全釋放的資源。 我不知道這是否也適用於套接字,我認為應該這樣做。
它還讓我看到了以前沒見過的記錄
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.