JVM Quest: MAT analysis of memory overflow

This series of notes is mainly based on "in-depth understanding of the Java Virtual Machine: JVM advanced features and best practices 2nd Edition" is a book of reading notes.

MAT is a tool for analyzing Java heap memory, the full name is The Eclipse Memory Analyzer Tool, to help analyze memory leaks and reduce memory consumption. MAT analysis using the Java heap snapshot, you can quickly calculate the reserve size (Retained Sizes) object, find reasons to prevent objects being recovered, MAT will automatically generate a report that contains a memory leak questionable.

MAT can be downloaded from the Eclipse Web site: http://www.eclipse.org/mat/

Generate Dump

MAT analysis using a Heap Dump, which is a snapshot of heap memory, a snapshot of the following ways:

  • Use the virtual machine parameters -XX: + HeapDumpOnOutOfMemoryError, automatically generates a snapshot overflow.
  • Use jmap command, jmap -dump: format = b, file = $ {dir} /jmap.hprof pid
  • Use MAT export the local java process memory snapshots, File-> Acquire Heap Dump-> Select dump the java process it.

MAT use

After you finish building the dump, you can open dump out of the snapshot file with MAT, File -> Open Heap Dump, to dump file for analysis, generate an Overview view:

image

First listed heap memory size, the number of classes, the number of objects, and how many class loader.

Then a pie chart Retained Size The size of the object is formed, put up the mouse, this object details Inspector left side view displays.

Then the other features, such as the commonly used charts, Histogram histogram, Dominator Tree dominator tree, also generates an analytical report Leak Suspects Report.

Basic concepts

Before continuing the analysis, to understand a few basic concepts.

Shallow Heap 和 Retained Heap

Shallow Heap表示对象本身占用内存的大小,不包含对其他对象的引用,也就是对象头加成员变量(不是成员变量的值)的总和。

Retained Heap是该对象自己的Shallow Heap,并加上从该对象能直接或间接访问到对象的Shallow Heap之和。换句话说,Retained Heap是该对象GC之后所能回收到内存的总和。

把内存中的对象看成下图中的节点,并且对象和对象之间互相引用。这里有一个特殊的节点GC Roots,这就是reference chain的起点。

image

从obj1入手,上图中蓝色节点代表仅仅只有通过obj1才能直接或间接访问的对象。因为可以通过GC Roots访问,所以左图的obj3不是蓝色节点;而在右图却是蓝色,因为它已经被包含在retained集合内。所以对于左图,obj1的retained size是obj1、obj2、obj4的shallow size总和;右图的retained size是obj1、obj2、obj3、obj4的shallow size总和。obj2的retained size可以通过相同的方式计算。

对象引用 Reference

关于对象的引用,前面的文章讲到过,划分如下:

  • 强引用(Strong Reference)就是在代码中普遍存在的,类似“Object obj = new Object()”这类的引用,只要强引用还存在,垃圾收集器永远不会回收被引用的对象。

  • 软引用(Soft Reference)是用来描述有用非必需的对象。软引用关联的对象,在系统将要发生内存溢出之前,将会对这些对象进行二次回收。如果这次回收后还没有足够的内存,才会抛出内存溢出异常。上面所说的“食之无味,弃之可惜”的对象就是属于软引用。

  • 弱引用(Weak Reference)是用来描述非必需的对象,但是比软引用更弱一些,弱引用关联的对象只能生存到下一次垃圾收集发生之前。当下一次垃圾收集时,无论内存是否足够,都会回收掉被弱引用关联的对象。

  • 虚引用(Phantom Reference)也称为幽灵引用或者幻影引用,它是最弱的一种引用。一个对象是否有虚引用存在,完全不会对其生存时间造成任何影响,也无法通过虚引用获得一个对象实例。为对象设置虚引用的目的,就是能在这个对象被收集器回收时收到一个系统通知。

四种引用中,只有强引用是强可达性,根据可达性分析回收内存时,永远不会被回收。

GC Roots 和 引用链

JVM在进行GC的时候是通过使用可达性来判断对象是否存活,通过GC Roots(GC根节点)的对象作为起始点,从这些节点开始进行向下搜索,搜索所走过的路径成为Reference Chain(引用链),当一个对象到GC Roots没有任何引用链相连(用图论的话来说就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。

如下图所示,对象Object 5、Object 6、Object 7虽然互相关联,但是它们到GC Roots是不可达的,所以它们将被判定为可回收的对象:

image

在 Java 中,可作为 GC Roots 的对象有以下几种:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象。
  • 方法区中类静态属性引用的对象。
  • 方法区中常量引用的对象。
  • 本地方法栈中 JNI(即一般说的 Native 方法)引用的对象。

四种引用,GC Roots以及引用链,可以参考之前的博客文章:《JVM探秘:四种引用、对象的生存与死亡》

Histogram 直方图

点击工具栏上的image图标,打开 Histogram 直方图视图,可以列出每个类产生的实例数量,以及所占用的内存大小和百分比。主界面如下图所示:

image

图中Shallow Heap 和 Retained Heap分别表示对象自身不包含引用的大小和对象自身并包含引用的大小,具体请参考下面 Shallow Heap 和 Retained Heap 部分的内容。默认的大小单位是 Bytes,可以在 Window - Preferences 菜单中设置单位,图中设置的是KB。

通过直方图视图可以很容易找到占用内存最多的几个类(通过Retained Heap排序),还可以通过其他方式进行分组(见下图):

image

如果存在内存溢出,时间久了溢出类的实例数量或者内存占比会越来越多,排名也越来越靠前。可以点击工具类上的image图标进行对比,通过多次对比不同时间点下的直方图对比就很容易把溢出的类找出来。

Dominator Tree 支配树

点击工具栏上的image图标可以打开Dominator Tree(支配树)视图,在此视图中列出了每个对象(Object Instance)与其引用关系的树状结构,同时包含了占用内存的大小和百分比。

image

通过Dominator Tree视图可以很容易的找出占用内存最多的几个对象(根据Retained Heap或Percentage排序),和Histogram类似,也可以通过不同的方式进行分组显示。

定位溢出源

Histogram视图和Dominator Tree视图的角度不同,前者是基于类的角度,后者是基于对象实例的角度,并且可以更方便的看出其引用关系。

First, find the two views overflow suspected object or class (Retained Heap by sorting, and may be regular expression keyword display only the specified class name in the Name Class entered), then right click Path To GC Roots (Histogram is not this) or Merge Shortest Paths to GC Roots, and select exclude all phantom / weak / soft etc. reference:

image

GC GC root Roots means, which have the meaning cited above and GC Roots chain moiety, the latter exclude all phantom / weak / soft etc. reference meant to exclude false, weak, soft and references cited, i.e. only strong references , because in addition to strong references, other references can be lost JVM GC, if an object is not always GC, it shows there is strong references exist, resulting in lack of recovery has been in the process of the GC, the final terms of memory overflow a.

By results can be easily positioned to a specific code, and then analyzed what the reasons are unable to release the object, such as was not cached or the like using a single-mode embodiment.

For example, if this is the result of execution:

image

The figure above retains a large number of external references VelocitySqlBulder, then looked at the code, the original time of each call instantiating a new object, due VelocitySqlBulder class is stateless tools, so amended as a single manner can be resolved this problem.

Follow-up observation

After the deal with the problem according to the results of the analysis above, and then control the operation before, and then see if the object has continued to grow, if not explain the problem this place has been resolved.

Finally jstat and then keep track of time, to see if the memory Old Perm region and the final stabilized within a range, if a long time in a stable range Description overflow problem has been resolved, or will continue to be analyzed and processed, has been to stable.

Guess you like

Origin www.cnblogs.com/cellei/p/12240241.html