在大型 Java 堆转储中查找内存泄漏的方法

我必须在Java应用程序中找到内存泄漏。我对此有一些经验,但希望就此的方法/策略提供建议。欢迎任何参考和建议。

关于我们的情况:

  1. 堆转储大于 1 GB
  2. 我们有5次堆转储。
  3. 我们没有任何测试用例来引发这种情况。它只发生在使用至少一周后的(大规模)系统测试环境中。
  4. 该系统建立在内部开发的遗留框架之上,该框架具有如此多的设计缺陷,以至于无法全部计算在内。
  5. 没有人能深入了解这个框架。它已被转移到印度的个人,他几乎跟不上回复电子邮件。
  6. 随着时间的推移,我们已经进行了快照堆转储,并得出结论,没有一个组件会随着时间的推移而增加。这是一切缓慢增长的东西。
  7. 以上为我们指出了一个方向,即正是框架自主开发的ORM系统可以无限制地增加其使用。(此系统将对象映射到文件?!所以不是真正的ORM)

问:是什么方法帮助您成功在企业级应用程序中发现泄漏?


答案 1

如果不了解底层代码,这几乎是不可能的。如果您了解底层代码,则可以更好地将小麦与堆转储中获取的大量信息的谷壳进行排序。

此外,您无法知道某些内容是否是泄漏,而不知道为什么该类首先存在。

在过去的几周里,我只是在做这件事,我使用了一个迭代过程。

首先,我发现堆分析器基本上没用。他们无法有效地分析巨大的堆。

相反,我几乎完全依赖于jmap直方图。

我想你熟悉这些,但对于那些不熟悉的人:

jmap -histo:live <pid> > histogram.out

创建活动堆的直方图。简而言之,它会告诉您类名,以及堆中每个类的实例数。

我定期倾倒堆,每5分钟,每天24小时。这对你来说可能太细化了,但要点是一样的。

我对这些数据进行了几次不同的分析。

我写了一个脚本来获取两个直方图,并转储它们之间的差异。所以,如果java.lang.String在第一个转储中是10,在第二个转储中是15,我的脚本会吐出“5 java.lang.String”,告诉我它上升了5。如果它下降了,这个数字将是负数。

然后,我会选取其中的几个差异,去掉从一个运行到运行的所有类,并取一个结果的并集。最后,我会有一个在特定时间跨度内不断增长的类列表。显然,这些是泄漏类的主要候选者。

但是,某些类保留了一些,而其他类则保留了一些。这些类在总体上很容易上下波动,但仍然会泄漏。因此,他们可能会从“不断上升”的类别中掉出来。

为了找到这些,我将数据转换为时间序列并将其加载到数据库中,特别是Postgres。Postgres很方便,因为它提供了统计聚合函数,因此您可以对数据进行简单的线性回归分析,并找到趋势上升的类,即使它们并不总是在图表的顶部。我使用了regr_slope函数,寻找具有正斜率的类。

我发现这个过程非常成功,而且非常有效。直方图文件并不是非常大,从主机下载它们很容易。它们在生产系统上运行的成本并不高(它们确实会强制使用大型GC,并且可能会阻塞VM一段时间)。我在一个具有2G Java堆的系统上运行它。

现在,所有这一切可以做的就是识别潜在的泄漏类。

这就是了解如何使用类,以及它们是否应该成为它们的地方。

例如,您可能会发现您有很多 Map.Entry 类或其他一些系统类。

除非你只是简单地缓存 String,否则事实是这些系统类,虽然可能是“违规者”,但不是“问题”。如果要缓存某个应用程序类,则该类可以更好地指示问题所在。如果您不缓存 com.app.yourbean,则不会将关联的 Map.Entry 绑定到它。

拥有一些类后,可以开始对代码库进行爬网以查找实例和引用。由于您有自己的ORM层(无论好坏),您至少可以很容易地查看它的源代码。如果你的ORM正在缓存东西,那么它可能会缓存ORM类来包装你的应用程序类。

最后,您可以做的另一件事是,一旦您知道了这些类,您就可以启动服务器的本地实例,其中包含更小的堆和更小的数据集,并使用其中一个探查器来对付它。

在这种情况下,您可以进行单元测试,该测试仅影响您认为可能泄漏的1个(或少量)内容。例如,您可以启动服务器,运行直方图,执行单个操作,然后再次运行直方图。你泄漏的类应该增加了1(或者你的工作单位是什么)。

探查器可能能够帮助您跟踪“现已泄露”类的所有者。

但是,最终,您必须对代码库有一定的了解,以便更好地了解什么是泄漏,什么不是,以及为什么某个对象存在于堆中,更不用说为什么它可能作为泄漏保留在堆中。


答案 2

看看Eclipse Memory Analyzer。这是一个很棒的工具(并且独立,不需要安装Eclipse本身),1)可以非常快速地打开非常大的堆,2)有一些非常好的自动检测工具。后者并不完美,但EMA提供了许多非常好的方法来浏览和查询转储中的对象,以查找任何可能的泄漏。

我过去曾使用它来帮助追捕可疑的泄漏。


推荐