12

我时不时地遇到一个奇怪的问题(实际上经常遇到)。

我正在运行一个服务器应用程序,它为自己绑定一个套接字。

但是偶尔,套接字并没有被释放。尽管 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://www.google.com/search?q=ps+process+is+exiting+osx

4

5 回答 5

3

尝试在每次测试后使用http://docs.oracle.com/javase/1.4.2/docs/api/java/net/ServerSocket.html#close ()关闭套接字 ,如果您还没有在拆解中.

于 2012-05-04T15:35:26.217 回答
3

这里只是在黑暗中拍摄,但要确保等待 Selector.select() 的任何线程都已被唤醒并退出。

于 2012-05-14T19:07:21.433 回答
2

因此,问题似乎在于 Mac 版本的 JDK 6 中 Selector 的实现。安装新的 Oracle JDK 7u4 解决了这个问题,与 Selector 的使用方式无关。

于 2012-05-24T15:24:30.243 回答
0

我也有 Parallels,而且通常问题看起来是由 Parallels 网络适配器引起的....

如果这个问题没有在其他平台上出现,我会说这是一个公平的赌注。你做了什么来排除 Parallels 作为罪魁祸首?

于 2012-05-10T06:17:32.143 回答
0

如果您认为资源没有正确释放,您可以尝试在shutdownhook中进行释放。像这样至少在它关闭时资源将被释放(如果你硬杀则不会)

一个非常基本的shutdownhook示例:

public void shutDownProceedure(){
    Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
            /* my shutdown code here */
        }
    });
}

这帮助我释放了以前没有完全释放的资源。我不知道这是否也适用于套接字,我认为应该。

它还让我看到了我以前从未见过的日志

于 2012-05-10T19:49:30.860 回答