【发布时间】:2014-03-08 04:02:04
【问题描述】:
我在 Java 中存在内存泄漏,其中我的堆转储中有 9600 个ImapClients,而只有 7800 个MonitoringTasks。这是一个问题,因为每个ImapClient 都应该归一个MonitoringTask 所有,所以那些额外的1800 个ImapClients 被泄露了。
一个问题是我无法在堆转储中隔离它们并查看是什么让它们保持活力。到目前为止,我只能通过使用外部证据来猜测ImapClients 悬挂在哪个位置上。我正在学习 OQL,我相信它可以解决这个问题,但它进展缓慢,而且我需要一段时间才能理解如何用新的查询语言执行这样的递归。
确定是否存在泄漏很困难,所以这是我的全部情况:
- 这个过程在一周前就已经产生了 OOME。我以为我已经修复了它,我正在尝试验证我的修复是否正常工作,而无需再等一整周来查看它是否再次喷出 OOME。
- 此任务在启动时创建 7000-9000
ImapClients,然后在正常操作下连接和断开其中的极少数。 - 我检查了另一个运行旧的预 OOME 代码的进程,它显示的数字是 9000/9100 而不是 7800/9600。我不知道为什么旧代码与新代码不同,但这是泄漏的证据。
这个问题的重点是我可以确定是否存在泄漏。有一个业务规则,每个ImapClient 都应该是MonitoringTask 的裁判。如果我要问的这个查询是空的,那么就没有泄漏。如果它提出了对象,连同这个业务规则,它不仅是泄漏的证据,而且是确凿的证据。
【问题讨论】:
-
有多少并发 ImapClient 活着?你能限制 ImapClient 对象的数量并重用它们吗?
-
@javaseeker 我绝对不能这样做。它们需要消失并被清理干净。
-
你确定ImapClient和MonitoringTask是分配在同一个堆类的,所以会一起收集吗?除了在 MonitoringTasks 中,您还会在哪里存储指向 ImapClients 的指针——如果它们真的被“泄露”(在这种略微扭曲的意义上),那是因为它们是从其他对象(可能是其他 ImapClients)引用的。
-
除了 MonitoringTask 之外,您是否曾经在任何其他对象中存储对 ImapClient 的引用?你说 ImapClient 是“更短暂的”——这是怎么发生的? ImapClient 引用是否设置为
null?您是否为单个 MonitoringTask 重复分配 ImapClients? -
如果您以高得多的速度创建 ImapClients,则很可能在任何时间点都会有更多的“已死但未收集”。
标签: java memory-leaks visualvm