【发布时间】:2010-11-16 11:35:46
【问题描述】:
我们在一个客户服务器上遇到了一个奇怪的问题,Java 遇到“文件过多”,
通过 lsof 检查描述符会产生大量带有“无法识别协议”的“sock”描述符。
我怀疑这是由于套接字打开时间过长造成的,但由于我们的线程转储包含很多套接字,我不清楚到底是谁造成的。
有什么好的方法可以检测哪些线程准确打开了这些套接字?
谢谢。
【问题讨论】:
我们在一个客户服务器上遇到了一个奇怪的问题,Java 遇到“文件过多”,
通过 lsof 检查描述符会产生大量带有“无法识别协议”的“sock”描述符。
我怀疑这是由于套接字打开时间过长造成的,但由于我们的线程转储包含很多套接字,我不清楚到底是谁造成的。
有什么好的方法可以检测哪些线程准确打开了这些套接字?
谢谢。
【问题讨论】:
有什么好的方法可以检测哪些线程确实打开了这些套接字?
不是线程本身。
一种方法是使用分析器运行应用程序。即使您不能准确地重现客户的问题,这也可以很好地找到问题。 (@SyBer 报告说 YourKit 分析器具有特定支持以查找套接字泄漏...请参阅评论。)
第二种方法是使用ulimit 调整您的测试平台,以减少允许的打开文件数。这可能更容易在您的测试环境中重现“打开的文件过多”的情况。
最后,我建议“grepping”您的代码库以查找创建套接字对象的所有位置。然后检查它们以确保它们正确使用 try / finally 块以确保套接字始终关闭。
【讨论】:
YourKit,还有其他免费选项吗?
从
开始netstat -ano | grep $YOUR_PROCESS_ID - 适用于 unix
netstat -ano | find "$YOUR_PROCESS_ID" - 适用于窗户
至少你会看到连接是否真的存在。
【讨论】:
--program 选项传递给 netstat 以输出进程 ID(即 PID)。
您是否尝试ulimit 来增加打开文件的数量?此外,您可能没有正确关闭套接字,因此您有泄漏。
【讨论】:
检测泄漏套接字的唯一“好”方法是非常详细的日志或分析器。执行内存转储并分析对象。
【讨论】:
Valgrind 将在您传递--track-fds=yes 时识别文件描述符泄漏。 Valgrind 在其跟踪的资源的“获取”点生成短堆栈跟踪。当您找到发生泄漏的源行后,您可以将其与 pthread_self 的返回值结合到您的日志系统(我确定您会使用一个!),或者放置breakpoints 在 gdb 中。
您可能忽略了已完成的close() 套接字。即使对等方启动关闭,也需要执行此操作。
【讨论】:
java 和linux 标签一起使用没有错。