我时不时地遇到一个奇怪的问题(实际上经常遇到)。
我正在运行一个服务器应用程序,它为自己绑定一个套接字。
但是偶尔,套接字并没有被释放。尽管 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 表示进程正在退出。我找不到任何方法可以在不重新启动的情况下完全终止这样的进程。其他一些应用程序也注意到了同样的问题。未找到解决方案: