【发布时间】:2012-12-25 12:42:08
【问题描述】:
我有一个运行很长时间的复杂 Java 应用程序。该应用程序一遍又一遍地执行相同的操作,几乎没有细微差别。 我的问题是 Windows 任务管理器显示了很多 Java 进程的泄漏句柄(不是文件句柄)。
在压力下运行应用程序一段时间后,我遇到了奇怪的故障,例如应用程序卡住、消失,或者在尝试打开文件时出现 FileNotFoundException(“系统资源不足,无法完成请求的服务”)。
我使用Windows任务管理器查看问题是什么,发现对于java.exe进程 - 句柄数量增加非常快。线程数没有增加,内存使用量也没有增加。
然后我使用 SysInternal 的 Process Explorer 来了解这些句柄是什么。我看到它们不是文件句柄,而是数千个“突变”类型的句柄,名称为 \BaseNamedObjects\??????n。 根据网络上的一些网站,Mutant in Process explorer 的意思是 Mutex。 我的 Java 应用程序不会有意创建任何互斥锁。
下一步是使用分析工具来缩小泄漏源的范围。 我使用了“J Optimizer”和“Java VirtualVM”。对于这两个应用程序,我无法检测到泄漏的句柄。他们有内存泄漏检测器,但我找不到检测泄漏句柄的方法。
我的问题是: 我该如何调试这个问题?如何找出导致手柄泄漏的原因?
谢谢
【问题讨论】:
-
如果您使用大量流资源,请确保在
try之前打开它们,然后在finally中关闭它们。但是没有代码,这很难猜到。 -
@baba 然后建议一种查找问题的方法。问题并不总是是什么。
-
@nos 是真的……但是问题是所使用的工具会寻找本地泄漏,并且这些资源和 Java 代码之间没有一对一的映射。例如,当
InputStream超出范围时,即使它被垃圾回收,底层 fd(如果有)也不是——除非您确保它已关闭。 -
您能否提供更多有关您的应用程序功能的信息?它是否打开套接字?如果是这样,您可能会泄露对这些的引用。它会创建许多短命线程吗?这些可能会成功完成运行,但仍可能以某种方式避免被垃圾收集。简而言之:它使用哪些资源进行运营?
-
@amnong 目前我只能想到两件事,按顺序: 1. 在所有代码中找到每个创建的实现
Closeable的实例,并确保所有这些实例都执行最终调用.close()(这也意味着在错误路径上); 2. 如果 1. 仍然泄漏,在从 1. 收集的数据的帮助下,交互式调试所有路径......是的,可撤销的。那么,另一个问题:你如何测试这些代码路径?
标签: java mutex memory-leaks handles