在Linux平台上使用套接字时是否存在文件描述符泄漏?
-
07-07-2019 - |
题
如果我通过调用实例
来打开和关闭套接字Socket s = new Socket( ... );
s.setReuseAddress(true);
in = s.getInputStream();
...
in.close();
s.close();
Linux声明此套接字仍处于打开状态,或者至少是连接的文件描述符。当通过lsof查询此进程的打开文件时,有一个关闭连接的条目:
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
java 9268 user 5u sock 0,4 93417 can't identify protocol
此条目将一直持续到程序关闭为止。有没有其他方法可以最终关闭套接字? 我有点担心我的java应用程序可能会阻塞许多文件描述符。这可能吗?或者,即使是设置了ReuseAdress,java还是会保留这些套接字来重用它们吗?
解决方案
如果这些套接字都处于TIME_WAIT状态,这是正常的,至少会持续一段时间。用netstat检查一下;套接字通常会挂起几分钟,以确保在重新使用新套接字的端口之前成功丢弃套接字中的分散数据。
其他提示
您可能还想检查/proc/<pid>/fd
,该目录将包含您当前打开的所有文件描述符。如果在关闭套接字后文件消失,则不会遇到任何问题(至少不会出现文件描述符:)。
我认为这不是你的程序问题。
在SUN_Java中,当加载与套接字相关的本机lib时,将创建一个MAGIC_SOCK fd。
写入MAGIC_SOCK会导致连接休息异常,并且读取MAGIC_SOCK将导致EOF。magic_sock的对等体已完全关闭,magic_sock本身为half_closed,状态将保持<!>“;无法识别协议<!>”。
也许它是一个其他协议的套接字(<!>“;无法识别协议<!>”;呃?)在实现中内部使用,以便在第一个套接字上创建。
您是否尝试重复创建套接字并关闭它们,以查看这些套接字是否真的存在?这似乎是一次性的。
Java可能在内部使用套接字来处理很多事情 - 它们可能是Unix,Netlink(在Linux下)或其他类型的套接字。
创建一个小的bash脚本来监视某个应用程序或pid的已打开的套接字,并让它在测试你的java应用程序时运行。
我怀疑这个东西有任何泄漏,因为套接字在linux / unix世界中很常用,而且这种问题会很快冒出来