大家好,欢迎来到IT知识分享网。
一、什么是heapdump
1、heapdump 介绍
- 对象信息:类名、属性、基础类型和引用类型
- 类信息:类加载器、类名称、超类、静态属性
- gc roots:JVM中的一个定义,进行垃圾收集时,要遍历可达对象的起点节点的集合
- 线程栈和局部变量:快照生成时候的线程调用栈,和每个栈上的局部变量
2、heapdump 用途
heapdump是诊断与JVM内存相关的问题的重要手段,例如:内存泄漏、垃圾回收问题和java.lang.OutOfMemoryError。同时也是优化内存消耗的重要手段。
3、JVM内存结构简述
内存为何会溢出
JVM根据generation(代)来进行GC,绝大多数的对象都在young generation被分配,也在young generation被收回,当young generation的空间被填满,GC会进行minor collection(次回收),速度非常快。其中,young generation中未被回收的对象被转移到tenured generation,当tenured generation被填满时,即触发major collection(FULL GC主回收),整个应用程序都会停止下来直到回收完成。
二、如何生成、导出heapdump
1、命令生成
jmap -dump:live,format=b,file=heapdump.hprof <pid> #如下命令亦可 jcmd <pid> GC.heap_dump heapdump.hprof
2、配置Java 启动参数生成
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/tmp/heapdump.hprof
三、基于MAT进行heapdump 分析
1、MAT工具介绍
mat(Eclipse Memory Analyzer tool),是一个快速且功能丰富的Java堆分析器,可帮助您查找内存泄漏并减少内存消耗。使用Memory Analyzer分析具有数亿个对象的高效堆转储,快速计算对象的保留大小,查看谁阻止垃圾收集器收集对象,运行报告以自动提取泄漏嫌疑者。
2、名词术语解释
在使用mat 前,先了解一些术语,便于工具的使用。
- Shallow heap:一个对象本身占用的堆内存大小,也就是对象头加成员变量(不是成员变量的值)的总和。一个对象中,每个引用占用8或64位,Integer占用4字节,Long占用8字节等等。
- Retained Heap:
如果一个对象被释放掉,那会因为该对象的释放而减少引用进而被释放的所有的对象(包括被递归释放的)所占用的heap大小,即对象被垃圾回收器回收后能被GC从内存中移除的所有对象之和。相对于shallow heap,Retained heap可以更精确的反映一个对象实际占用的大小(若该对象释放,retained heap都可以被释放)。 - gc root: 在java语言中,都是通过可达性分析来判定对象是否存活的。此算法的基本思路是:通过一系列的称为“GC Roots”的对象作为起点,从这些节点向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连,则证明此对象是不可达的,因此能被GC 回收掉。因此可以得出,只有引用类型的变量才被认为是Roots,值类型的变量永远不被认为是Roots。GCROOT的目标对象是要以当前还在存活的对象集合,因此必须要选取确定存活的引用类型对象,GC管理的区域是java的堆,虚拟机栈、方法区和本地方法栈不被GC所管理,因此选用这些区域内引用的对象作为GC Roots,是不会被GC回收的。
3、MAT功能模块介绍
为方便后续功能理解使用,先阐述几个通用功能
1.List object:其下有with outgoing references,with incoming references两个选项。
with outgoing references:查看当前对象持有的外部对象引用(在对象关系图中为从当前对象指向外的箭头)
with incoming references:查看当前对象被哪些外部对象所引用(在对象关系图中为指向当前对象的箭头)
2.Paths to GC Roots:从当前对象到GC roots的路径,这个路径解释了为什么当前对象还能存活,对分析内存泄露很有帮助,这个查询只能针对单个对象使用。其下有很多选项,在查询到GC root的路径时,是包含所有引用,还是排除一些类型的引用(如软引用、弱引用、虚引用),从GC角度说,一个对象无法被GC,一定是因为有强引用存在,其它引用类型在GC需要的情况下都是可以被GC掉的,所以可以使用 exclude all phantom/weak/soft etc. references 只查看GC路径上的强引用
- Histogram:直方图,可以列出内存中的对象,对象的个数以及大小。
该视图以Class类的维度展示每个Class类的实例存在的个数、 占用的 [Shallow内存] 和 [Retained内存] 大小,可以分别排序显示。
从Histogram视图可以看出,哪个Class类的对象实例数量比较多,以及占用的内存比较大,Shallow Heap与Retained Heap的区别会在后面的概念介绍中说明。
不过,多数情况下,在Histogram视图看到实例对象数量比较多的类都是一些基础类型,如char[]、String、byte[],所以仅从这些是无法判断出具体导致内存泄露的类或者方法的,可以使用 List objects或 Merge Shortest Paths to GC roots 等功能继续钻取数据。如果Histogram视图展示的数量多的实例对象不是基础类型,是有嫌疑的某个类,如项目代码中的bean类型,那么就要重点关注了。
- Dominator Tree:支配树,可以列出那个线程,以及线程下面的那些对象占用的空间。
该视图以实例对象的维度展示当前堆内存中Retained Heap占用最大的对象,以及依赖这些对象存活的对象的树状结构
视图中展示了实例对象名、Shallow Heap大小、Retained Heap大小、以及当前对象的Retained Heap在整个堆中的占比
Dominator Tree支配树可以很方便的找出占用Retained Heap内存最多的几个对象,并表示出某些objects的是因为哪些objects的原因而存活,在之后的 Dominator Tree概念 部分会对支配树做更详细的说明和举例 - Top consumers:通过图形列出最大的object
可以通过按包名查看区分占用,根据包我们知道哪些公共用的到jar或自己的包占用 - Thread Overview
在Thread Overview视图可以看到:线程对象/线程栈信息、线程名、Shallow Heap、Retained Heap、类加载器、是否Daemon线程等信息
在分析内存Dump的MAT中还可以看到线程栈信息,这本身就是一个强大的功能,类似于jstack命令的效果
而且还能结合内存Dump分析,看到线程栈帧中的本地变量,在左下方的对象属性区域还能看到本地变量的属性,真的很方便 - Leak Suspects通过MA自动分析泄漏的原因
Leak Suspects 是MAT帮我们分析的可能有内存泄露嫌疑的地方,可以体现出哪些对象被保持在内存中,以及为什么它们没有被垃圾回收。MAT工具分析了heap dump后在界面上非常直观的展示了一个饼图,该图深色区域被怀疑有内存泄漏,
接下来是一个简短的描述,告诉我们哪些线程占用了大量内存,并且明确指出system class loader加载的实例有内存聚集,并建议用关键字对应进行检查。在下面还有一个“Details”链接,可以查看明细信息。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/115170.html





