自动heap dump 分析:轻松发现内存泄露

这篇文章想通过一个内存映像文件来找出内存泄露。本文将给出一些获取有力数据进行分析的几个小技巧。一会将描述如何使用MAT进行自动分析。自动分析将大大降低找出内存问题的复杂性,可以使小白轻松分析内存问题。你需要做的就是提供一个可用的heap dump 文件,然通过单纯一个Java堆映像是不足以发现内存泄露的。通常的做法是在线分析监控某些类对象的增长情况,或者比较不同时间的多个内存映像文件。在线分析往往不可行并且在生产环境分析是非常困难的,因为使用分析器会损耗性能,并且很多内存泄露只有在某些特定的情况下才会出现。 MAT 将会为你创建一份包含泄露猜测的报告。下文将会讲解这份报告包含什么以及如何分析这些报告。

准备工作

首先要做的是收集足够的数据。这非常简单,当JVM发生OOME时 输出heap dump 文件即可。这不需要你自己手动去dump. 只需要添加jvm参数 -XX:+HeapDumpOnOutOfMemoryError 即可。 (也可以参考这篇文章 http://wiki.eclipse.org/MemoryAnalyzer#Getting_a_Heap_Dump)

准备工作的第二步是使内存泄漏变得显而易见和易检测。可以通过如下的方法做到这一点: 将堆的max size 配置的比程序正常运行时需要的堆大小大很多(比如将它设置为full gc 之后堆内存大小的两倍),如果你不知道应用程序需要多大的堆内存,将增大堆的大小不失为一个好的做法(结果可能表明没有泄露,而是仅仅需要更多的堆内存而已)。

当发生OOME时,将会输出一个heap dump 文件。很可能泄露对象的大小占用当前heap dump 文件一半左右的空间,如果这样,将会很简单地分析出泄露。

执行分析

有了heap dump 文件,接下来进行分析。打开MAT,然后看到一个overview, 里面包含了一个饼状图,在这个图中你可能已经看到了一个很大的对象。

但是这还不是泄露疑点报告。 点击 leak suspects ,将会看到。

这就是你所有需要做的内容。这款工具里面有一些功能可以找出可疑的大对象。然后需要找的就是一些综合但是易于理解的html 报告。HTML生成之后将会呈现出现。同时会生成一个zip文件。可以将这个文件传输给同事,进行咨询。而不需要传输heap dump 文件。

报告内容 - 疑点概述

生成之后,如下图展示

先看到一个饼状图。黑色部分占用很大。然后是一个简短的描述。占了591.58M,占用90.48%的堆空间。 然后告诉我们这个实例是来自 java.util.concurrent.ConcurrentHashMap.

仅仅凭借上述几点,给了一个简单直观的阐述,问题出在哪儿,占据内存的类的名称,这个类属于哪个类或对象, 占了多大空间。

然后报告提供了keywords,这有什么用?分析报告的一个目的是发现已知问题。因此我们需要给每一个可疑点提供一个唯一标识符,这些标识符可以用来查询一个已经存在错误跟踪(bug-tracking)的系统。所有报告中的keywords 就是这些标识符。可以用来多个人之间分析报告。如果一个人提供了这个报告中的keyword,其他人可以用这个keyword 找到它,并分析。

到目前为止,通过点击鼠标可以发现可疑问题点,对于找出问题解决方案提供了信息。即使代码不是自己写的,也没有任何定位内存问题的经验,我也可以找到可能存在的问题。

报告内容 - 问题详述

除了内存泄露概述,还可以看详情。详情里面可以看到什么?在分析真实环境问题时,当发现泄露可疑点的时候通常会想到两个问题:

  • 为什么内存中有累积的对象?或者谁在引用他们?
  • 为什么对象如此之大?里面的内容是什么?

本文将尝试给出这个两个问题的答案。首先可以看到从GC Roots到该增长点的最短路径。

通过这个图可以看到这些类和属性的路径,如果你对代码比较熟悉,就可以看出这些对象是如何存储的。

然后(为了回答为什么对象如此之大?)报告包含了很有有关增长内容的信息:

通过上图可以看到那些对象堆积。

报告内容 - 系统总览

现在有了问题详解,再看下另外一部分 - “系统总览”。一旦问题确认,就会想“在什么条件下会出现这个现象?” 或者”场景是什么?“ 。为了得到问题的答案,我们看一下”System Overview“ 页面。这个页面包含除了heap dump 之外的一些不同的细节,这可以帮助你理解问题出现的上下文环境。这些细节包括:

  • 有关heap dump 文件的一些信息:大小,类的数量,类加载器的数量等。
  • 系统属性
  • 镜像文件输出时运行的线程的总览
  • 顶级消费者 - 比如大对象,类,类加载器,包
  • 有关类的直方图

通过现象看本质 - 找出泄露疑点

现在解释一下我们是如何找到泄露疑点的。heap dump 文件打开的第一次,创建了这个文件的索引,这些索引便于我们后续分析。第一次解析的时候,也创建了支配树(dominator tree)。支配树在我们分析和寻找可疑点时起到了至关重要的作用。仅仅通过一些线去分析支配树背后的图表原理是非常困难的,因此本文会尝试列举几个通过使用它获得几个重要的知识点:

  • 支配树表明了对象之间的依赖关系。在这颗树中,每个对象使得其依赖存活。这意味如果一个对象被回收,则其依赖也要被回收。这些对象占用的所有内存空间成为这个对象的retained size.
  • 支配树可以展示堆中最大的对象们。使用依赖关系很容易算出对象的retained size。所以按照大小将对象进行排序是很简单的。

下面讲一下如何利用支配树找到泄露可疑点。看下面的图,这个图中展示了支配树的一部分,图中的圆代表对象的retaind size: 圆越大,占用的内存越大。

很容易地就可以将大小超过某些阈值的对象列为可疑点。然后我们沿着支配树下移,尝试找到一些占用内存很小,但是数量很多的小对象,这些点称为 ”Accumalation point“。 我们仅仅利用这两类对象(suspect 和 累积点)就可以去描述问题所在。

另外,还有一篇博客,可以协助理解。只是使用工具版本不同而已。

总结

在线跟离线分析内存映像各有利弊。MAT是个好工具。有很多优点:无运行时性能损耗,VM在oom时自动输出heap dump 文件,自动分析很简单。- 这使得分析起来比较简单,特别是针对有问题的线上环境。

参考文献:

原文地址: http://memoryanalyzer.blogspot.com/2008/05/automated-heap-dump-analysis-finding.html

results matching ""

    No results matching ""