获得堆转储文件

巧妇难为无米之炊,我们首先需要获得一个堆转储文件。为了方便,本文采用的是 Sun JDK 6。通常来说,只要你设置了如下所示的 JVM 参数:

-XX:+HeapDumpOnOutOfMemoryError

JVM 就会在发生内存泄露时抓拍下当时的内存状态,也就是我们想要的堆转储文件。

如果你不想等到发生崩溃性的错误时才获得堆转储文件,也可以通过设置如下 JVM 参数来按需获取堆转储文件。

-XX:+HeapDumpOnCtrlBreak

除此之外,还有很多的工具,例如 JMap,JConsole 都可以帮助我们得到一个堆转储文件。本文实例就是使用 JMap 直接获取了 Eclipse Galileo 进程的堆转储文件。您可以使用如下命令:

JMap -dump:format=b,file=<dumpfile> <pid>

不过,您需要了解到,不同厂家的 JVM 所生成的堆转储文件在数据存储格式以及数据存储内容上有很多区别, MAT 不是一个万能工具,它并不能处理所有类型的堆存储文件。但是比较主流的厂家和格式,例如 Sun, HP, SAP 所采用的 HPROF 二进制堆存储文件,以及 IBM 的 PHD 堆存储文件等都能被很好的解析(您需要安装额外的插件,请参考 相关说明,本文不作详细解释)。

万事俱备,接下来,我们就可以开始体验一键式的堆存储分析功能了。

参考链接:

https://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-ma/index.html

Java性能分析工具和命令

https://www.ibm.com/developerworks/cn/java/j-lo-performance-analysissy-tools2/index.html

Memory Analyzer Tool 使用

最近一段时间一直在研究热部署,热部署中涉及到一个比较头痛的问题就是查内存泄露(Memory Leak),于是乎在研究热部署的过程中,干的最多的一件事就是查内存泄露。
       查内存泄露,最开始尝试用JDK自身的工具去解决这件事,通过jstat和jmap,去发现是否有内存泄露,当判断有内存泄露存在时,试图要去寻找内存泄露的点时,发现单纯使用JDK自身提供的工具没有什么很好的办法,我尝试过Jhat,发现查起来太困难了,后来对比网上推荐的工具,我选择了MAT(Memory Analyzer Tool)。
       MAT是一个eclipse的插件,上手起来比较快。它能够快速的分析dump文件,可以直观的看到各个对象在内存占用的量大小,以及类实例的数量,对象之间的引用关系,找出对象的GC Roots相关的信息,此外还能生成内存泄露报表,疑似泄露大对象的报表等等。

  • 安装MAT
  • 可以选择eclipse插件的方式安装
    • http://download.eclipse.org/mat/1.3/update-site/
  • 也可以选择单独MAT程序下载安装
    • http://www.eclipse.org/mat/downloads.php
  • 使用MAT查内存溢出
    • 生成dump
  • 生成dump文件,可以直接用 jmap -dump:format=b,file=xxx.bin ${pid}的方式
  • 也可以直接用MAT生成,File-》Acquire Heap Dump -》选择要dump的java进程-》finish就可以了
  • 生成完dump后,可以用MAT打开 dump(如果是MAT dump完后会自动进行解析),File-》Open Heap Dump 对dump文件进行解析,最终生成一个Overview视图,这个图是一个概要图,显示了一些统计信息,包括整个size大小,class数量,以及对象 的数量,同时还将生成一个大对象的top图,并线显示大对象占用内存的百分比。
    • 类似:size:2.2MB Classes:3.3k Objects:50.1k ClassLoader:84 Unreachable Objects Histogram
    • 找出溢出源
      • Histogram视图(截图里柱子那个,边上的是Dominator Tree ):列出每個class产生了多少個实例,以及占有多大内存,所占百分比
        • 可以很容易找出站内存最多的几个类,根据Retained Heap排序,找出前几个。
        • 可以分不同的维度来查看类的Histogram视图,Group by class、Group by superclass、Group by class  loader、Group by package
        • 只要有溢出,时间久了,溢出类的实例数量或者其占有的内存会越来越多,排名也就越来越前,通过多次对比不同时间点下的Histogram图对比就能很容易把溢出类找出来。
        • Dominator Tree(支配树):列出每个对象(Object instance)与其引用关系的树状结构,还包含了占有多大内存,所占百分比
  • 可以很容易的找出占用内存最多的几个对象,根据Percentage(百分比)来排序。
  • 可以分不同维度来查看对象的Dominator Tree视图,Group by class、Group by class  loader、Group by package
  • 和Histogram类似,时间久了,通过多次对比也可以把溢出对象找出来,Dominator Tree和Histogram的区别是站的角度不一样,Histogram是站在类的角度上去看,Dominator Tree是站的对象实例的角度上看,Dominator Tree可以更方便的看出其引用关系。
    • 定位溢出的原因
      • 通过Path to GC Roots或者Merge Shortest Paths to GC Roots
  • 通 过Histogram视图或者Dominator Tree视图,找到疑似溢出的对象或者类后,选择Path to GC Roots或者Merge Shortest Paths to GC Roots,这里有很多过滤选项,一般来讲可以选择exclude all plantom/weak/soft etc. references。这样就排除了虚引用、弱引用、以及软引用,剩下的就是强引用。从GC上说,除了强引用外,其他的引用在JVM需要的情况下是都可以 被GC掉的,如果一个对象始终无法被GC,就是因为强引用的存在,从而导致在GC的过程中一直得不到回收,因此就内存溢出了。
  • 接下来就需要直接定位具体的代码,看看如何释放这些不该存在的对象,比如是否被cache住了,还是其他什么原因。
  • 找到原因,清理干净后,再对照之前的操作,看看对象是否还再持续增长,如果不在,那就说明这个溢出点被成功的堵住了。
  • 最后用jstat跟踪一段时间,看看Old和Perm区的内存是否最终稳定在一个范围内,如果长时间稳定在一个范围,那溢出的问题就解决了,如果还再继续增长,那继续用上述方法,看看是否存在其他代码的溢出点,继续找出,将其堵住。
      • 此外通过list objects或show objects by class也可以达到类似的效果,不过没看GC Roots的方式直观,这里就不细说了。
        • list objects -- with outgoing references : 查看这个对象持有的外部对象引用。
        • list objects -- with incoming references : 查看这个对象被哪些外部对象引用。
        • show objects by class  --  with outgoing references :查看这个对象类型持有的外部对象引用
        • show objects by class  --  with incoming references :查看这个对象类型被哪些外部对象引用

参考链接:

http://wensong.iteye.com/blog/1986449

MAT - Memory Analyzer Tool 使用进阶

http://www.lightskystreet.com/2015/09/01/mat_usage/

MAT分析器中的shallow and retained heap详解

http://blog.csdn.net/u013309870/article/details/52038407

性能分析工具

http://www.importnew.com/12324.html

JVM性能分析工具详解--MAT等的更多相关文章

  1. valgrind和Kcachegrind性能分析工具详解

    一.valgrind介绍 valgrind是运行在Linux上的一套基于仿真技术的程序调试和分析工具,用于构建动态分析工具的装备性框架.它包括一个工具集,每个工具执行某种类型的调试.分析或类似的任务, ...

  2. Android 常用的性能分析工具详解:GPU呈现模式, TraceView, Systrace, HirearchyViewer(转)

    此篇将重点介绍几种常用的Android性能分析工具: 一.Logcat 日志 选取Tag=ActivityManager,可以粗略地知道界面Displaying的时间消耗.当我们打开一个Activit ...

  3. JVM性能调优详解

    前面我们学习了整个JVM系列,最终目标的不仅仅是了解JVM的基础知识,也是为了进行JVM性能调优做准备.这篇文章带领大家学习JVM性能调优的知识. 性能调优 性能调优包含多个层次,比如:架构调优.代码 ...

  4. [转帖]JVM性能调优详解

    JVM性能调优详解 https://www.cnblogs.com/secbro/p/11833651.html 应该是 jdk8 以前的方法 貌似permsize 已经放弃这一块了. 前面我们学习了 ...

  5. Linux性能分析工具top命令详解

    top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,常用于服务端性能分析. top命令说明 [www.linuxidc.com@linuxidc-t-tomcat-1 ...

  6. Java 性能分析工具 , 第 2 部分:Java 内置监控工具

    引言 本文为 Java 性能分析工具系列文章第二篇,第一篇:操作系统工具.在本文中将介绍如何使用 Java 内置监控工具更加深入的了解 Java 应用程序和 JVM 本身.在 JDK 中有许多内置的工 ...

  7. Chrome开发者工具详解(4)-Profiles面板

    Chrome开发者工具详解(4)-Profiles面板 如果上篇中的Timeline面板所提供的信息不能满足你的要求,你可以使用Profiles面板,利用这个面板你可以追踪网页程序的内存泄漏问题,进一 ...

  8. Chrome开发者工具详解(3)-Timeline面板

    Chrome开发者工具详解(3)-Timeline面板 注: 这一篇主要讲解面板Timeline,参考了Google的相关文档,主要用于公司内部技术分享.. Timeline面板 Timeline面板 ...

  9. Chrome开发者工具详解(2)-Network面板

    Chrome开发者工具详解(2)-Network面板 注: 这一篇主要讲解面板Network,参考了Google的相关文档,主要用于公司内部技术分享. Chrome开发者工具面板 面板上包含了Elem ...

随机推荐

  1. 解决官网下载jdk只有5k大小的错误

    问题现象 官网 https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 我选择linu ...

  2. 使用virtualenv, uwsgi, nginx来布署django

    http://blog.csdn.net/lihao21/article/details/47731903 http://www.cnblogs.com/lxg226/p/3468558.html h ...

  3. ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock'

    原因:找不到mysql.sock文件 解决方法: 1 找到mysql.sock文件位置 echo "show variables" | mysql | grep "soc ...

  4. 解决Linux下AES解密失败

    前段时间,用了个AES加密解密的方法,详见上篇博客AES加密解密. 加解密方法在window上測试的时候没有出现不论什么问题.将加密过程放在安卓上.解密公布到Linuxserver的时候,安卓将加密的 ...

  5. 模拟利器Mockito

    16.3.1  模拟测试概述 目前支持Java语言的Mock测试工具有EasyMock.JMock.Mockito.MockCreator.Mockrunner.MockMaker等,Mockito是 ...

  6. 微信小程序-上传多张图片加进度条(支持预览、删除)

    2018-12-24 详情示例见:https://www.cnblogs.com/cisum/p/9564898.html 2018-12-29 组件下载见:https://www.cnblogs.c ...

  7. JAVA中大数经常使用的函数

    声明为 BigInteger 的 java.math 中的字段 static BigInteger BigInteger. ONE BigInteger 的常量 1. static BigIntege ...

  8. linux驱动开发重点关注内容--摘自《嵌入式Linux驱动模板精讲与项目实践》

    本文摘自本人拙著 <嵌入式Linux驱动模板精讲与项目实践> 初步看起来Linux设备驱动开发涉及内容非常多,而须要实现驱动的设备千差万别.事实上做一段时间驱动之后回首看来主要就是下面几点 ...

  9. 又一次认识java(九) ---- 内部类

    注意注意!! ! 前排提示!!.本篇文章过长,最好收藏下来慢慢看.假设你之前对内部类不是非常熟悉,一次性看完,大概你会懵逼. . . 1. 内部类概述 一个类的定义放在还有一个类的内部,这个类就叫做内 ...

  10. uwsgi报错:listen queue of socket ...

    Linux默认的socket链接为128,uwsgi默人的链接为100 需要修改系统默认的配置参数, 然后修改uwsgi配置:listen参数:1024