JVM故障分析及性能优化系列文章

上一篇文章概括的介绍了JVM Heap Dump文件生成的方式以及内存分析工具MAT的概要功能,今天讲解如何使用MAT的Histogram和Dominator Tree两个视图,定位到内存溢出源。

基础概念

先列出几个基础的概念:

Shallow Heap 和 Retained Heap

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

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

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

从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 Ref):通常我们编写的代码都是强引用,于此相对应的是强可达性,只有去掉强可达性,对象才能被回收。

软引用(Soft Ref):对应软可达性,只要有足够的内存就一直保持对象,直到发现内存不足且没有强引用的时候才回收对象。

弱引用(Weak Ref):比软引用更弱,当发现不存在强引用的时候会立即回收此类型的对象,而不需要等到内存不足。通过java.lang.ref.WeakReference和java.util.WeakHashMap类实现。

虚引用(Phantom Ref):根本不会在内存中保持该类型的对象,只能使用虚引用本身,一般用于在进入finalize()方法后进行特殊的清理过程,通过java.lang.ref.PhantomReference实现。

GC Roots和Reference Chain

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

如下图所示,对象object 5、object 6、object 7虽然互相有关联,它们的引用并不为0,但是它们到GC Roots是不可达的,因此它们将会被判定为是可回收的对象。

Histogram(直方图)视图

点击工具栏上的

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

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

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

如果存在内存溢出,时间久了溢出类的实例数量或者内存占比会越来越多,排名也越来越靠前。可以点击工具类上的

图标进行对比,通过多次对比不同时间点下的直方图对比就很容易把溢出的类找出来。

还有一种对比直方图的方式,首先通过 Window 菜单打开 Navigation History 视图,选中直方图右键并选中 Add to Compare Basket项目,将直方图添加到 Compare Basket 中。

然后在 Compare Basket 中点击右上角的

按钮,可以分别列出对比的所有结果,见下图:

并且在上面的可以设置不同的对比方式。

Dominator Tree视图

点击工具栏上的

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

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

定位溢出源

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

首先,在两个视图中找出疑似溢出的对象或者类(可以通过Retained Heap排序,并且可以在Class Name中输入正则表达式的关键词只显示指定的类名),然后右键选择Path To GC Roots(Histogram中没有此项)或Merge Shortest Paths to GC Roots,然后选择 exclude all phantom/weak/soft etc. reference:

GC Roots意为GC根节点,其含义见上面的 GC Roots和Reference Chain 部分,后面的 exclude all phantom/weak/soft etc. reference 意思是排除虚引用、弱引用和软引用,即只剩下强引用,因为除了强引用之外,其他的引用都可以被JVM GC掉,如果一个对象始终无法被GC,就说明有强引用存在,从而导致在GC的过程中一直得不到回收,最终就内存溢出了。

通过结果就可以很方便的定位到具体的代码,然后分析是什么原因无法释放该对象,比如被缓存了或者没有使用单例模式等等。

下面是执行的结果:

上图中保留了大量的VelocitySqlBulder的外部引用,后来查看了代码,原来每次调用的时候都实例化一个新的对象,由于VelocitySqlBulder类是无状态的工具类,因此修改为单例方式就可以解决这个问题。

后续观察

根据上面分析的结果对问题进行处理之后,再对照之前的操作,看看对象是否还再持续增长,如果没有就说明这个地方的问题已经解决了。

最后再用 jstat 持续跟踪一段时间,看看Old和Perm区的内存是否最终稳定在一个范围之内,如果长时间稳定在一个范围说明溢出问题得到了解决,否则还要继续进行分析和处理,一直到稳定为止。

java7 调优_JVM故障分析及性能优化系列之七:使用MAT的Histogram和Dominator Tree定位溢出源...相关推荐

  1. Java虚拟机这一块 —— JVM 调优和深入了解性能优化

    JVM 调优和深入了解性能优化 JVM 调优的本质 GC 调优原则 调优的原则 目的 GC 调优 调优步骤 日志分析 阅读 GC 日志 -XX:+UseSerialGC -XX:+UseParNewG ...

  2. SQL调优与报表的性能优化

    原文链接:https://www.iteye.com/blog/shensy-1664549   作者:shensy 一.SQL调优: 1.提升统计查询性能,首当其冲当然还是对查询SQL进行优化,说到 ...

  3. mysql报表统计 优化_关于SQL调优与报表的性能优化

    前一段时间做了某产品实时统计的报表,这周在对报表性能进行优化. 其中逐步积累了一些优化经验,总结一下记录下来,欢迎大家一起探讨. 本文仅限于探讨单个数据库的查询sql及统计报表调优,不涉及分布式数据库 ...

  4. JVM性能调优6_深入了解性能优化__享学课堂

    常用的性能评价/测试指标  响应时间  提交请求和返回该请求的响应之间使用的时间,一般比较关注平均响应时间.  如:数据库查询花费的时间,将字符回显到终端上花费的时间,访问 Web 页面花费的时 ...

  5. JVM性能调优(4)——性能调优工具

    目录 一.JDK工具1.JDK工具2.利用 jps 找出进程3.利用 jstat 查看VM统计信息4.利用 jmap 查看对象分布情况5.利用 jstack 分析线程栈 二.Linux 命令行工具1. ...

  6. 【转载】软件性能测试分析与调优实践之路-性能分析调优思想与调优技术总结

    本文主要阐述软件性能测试中的一些调优思想和技术,节选自作者新书<软件性能测试分析与调优实践之路>部分章节归纳. 一.  性能分析与调优思想 1.性能分析调优模型 性能测试除了为获取性能指标 ...

  7. 软件性能测试分析与调优实践之路-性能分析调优思想与调优技术总结

    来源:https://www.cnblogs.com/laoqing/p/13660768.html 本文主要阐述软件性能测试中的一些调优思想和技术,节选自作者新书<软件性能测试分析与调优实践之 ...

  8. 推荐:Java性能优化系列集锦

    Java性能问题一直困扰着广大程序员,由于平台复杂性,要定位问题,找出其根源确实很难.随着10多年Java平台的改进以及新出现的多核多处理器,Java软件的性能和扩展性已经今非昔比了.现代JVM持续演 ...

  9. iOS性能优化系列篇之“列表流畅度优化”工具篇

    这一篇文章是iOS性能优化系列文章的的第二篇,主要内容是关于列表流畅度的优化.在具体内容的阐述过程中会结合性能优化的总体原则进行分析,所以建议大家在阅读这篇文章前先阅读一下上一篇文章:iOS性能优化系 ...

  10. 【Linux 性能优化系列】Linux 性能优化 -- CPU 性能篇(三) Linux 软中断

    [Linux 性能优化系列]Linux 性能优化 -- CPU 性能篇(三) Linux 软中断 [1]相关概念 [1.1]中断 中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力:为了减少 ...

最新文章

  1. Docker 下安装 Spark
  2. Linux 如何获取PAGE size的大小?
  3. jquery 遍历java对象的属性_用jquery each标签遍历java list对象
  4. mysql中数据定义语言_SQL数据定义语言(DDL)
  5. ajax请求 304解决方案:
  6. [基础]全局组、域本地组、通用组的区别与联系
  7. 如何在Pr中应用混合模式合成影片中的剪辑?
  8. 软件研发相关国家标准汇总
  9. matlab图像滤波详解(二维傅里叶滤波)
  10. android 时钟翻转,旋转时钟游戏
  11. Win10家庭中文版开机后弹窗无法登录到你的账户点注销没用(解决过程记录)
  12. 牛客网 哈夫曼树 (大根堆、哈夫曼树)
  13. python爬虫自学笔记_Python2.x自学笔记(二)——简单爬虫
  14. 使用expect ftp免交互上传文件
  15. python中import random_[零基础学python]Import 模块
  16. php的api系统,php api 框架
  17. 把全角数字(及字母)转换成半角数字
  18. 编写时间类代码(实现时分秒的增与减)
  19. 检验 pytorch,tensorflow,paddle,mxnet 深度学习框架是否正确支持GPU功能
  20. hands on Ml with scikitlearn TF

热门文章

  1. ArduinoProteus 8 Professional——(超声波检测传感器SRF04(距离检测))for Neuedu
  2. 你知道两台Linux之间如何传输文件吗?
  3. 计算机excel实验结果分析,使用Excel2013分析管理表格数据实训演练——想象力电脑应用...
  4. 二维码编辑网站推荐,哪个更好用?
  5. python arduino i2c1602_Arduino使用I2C转接板驱动1602液晶屏,小小白新手入门篇
  6. 姿态估计1-06:FSA-Net(头部姿态估算)-源码无死角讲解(1)-训练代码总览
  7. 计算机公共基础知识论文,公共基础知识学术论文.docx
  8. linux系统软路由软件,使用Linux+Zebra构建软路由系统
  9. Linu基本知识(二)——Linux系统以及相关命令
  10. vue全局混入minx