摘要:介绍内存分析工具Mat查找大对象的使用方法,定位full GC根源,拉升系统吞吐量,避免内存泄漏。

引言

  线上服务器频繁发生full GC,直接拉低系统吞吐量,甚至OOM。今天我们来一起学习一下如何利用MAT(Memory Analyzer Tool)快速的定位Java程序的大对象和内存泄漏问题。本文实验环境为Mac下安装独立版的Eclipse Memory Analyzer Version 1.13.0。

  对于程序员来说码代码容易,保证代码的稳定性很难。有时候写完一个功能可能只需要一天时间,但是这个功能隐藏的bug导致的线上问题排查可能需要一周或者更长时间。因此,拥有良好的代码结构和编码规范是一个程序员应该长期坚持并为之奋斗的一个目标。但是,百密也难免一疏,没有百分之百没有问题的代码,在产品上线前,我们需要对自己的代码进行充分的自测,解决发现问题,保证产品的稳定性并减少对用户的困扰。今天,就给大家简单介绍一下如何使用MAT(Memory Analyzer Tools)进行Android内存泄漏分析,我只是抛砖引玉,希望大家能够灵活地将这个强大的工具使用起来。

  什么是Dump文件?Dump文件也称为内存转储文件或内存快照文件,是一个进程或者系统在某一个给定时间的内存快照。例如当进程崩溃或进程出现其它问题时,甚至在任何时候,我们都可以使用工具备份系统或进程的内存进行调试和分析。它包含模块信息、线程信息、堆栈调用信息、异常信息等。

查看java服务进程pid

  若想查看指定的进程,如java进程,可以通过管道符和grep命令进行查询,命令如下:

ps -aux | grep java

or

jps -l

JMAP导出dump 文件

  在使用mat进行内存分析前,需要准备好Heap dump文件,避免服务重启后无法复现问题。输出jvm的heap内容到指定文件,live子选项是可选的,假如指定live选项,那么只输出活的对象到文件:

jmap -dump:live,format=b,file=myFullGcDump.bin

  替换为上一节拿到的服务进程号即可,此命令将把dump信息导入到myFullGcDump.bin文件中,供下文分析使用。

  大家在使用上述命令时候一定要小心,如果服务器上的JVM heap过大,会造成应用“Stop the World”。建议使用参数的形式,在启动应用程序的时候就把参数带上,这样会在内存溢出的时候及时的保存线程dump文件。

  把服务器上的myFullGcDump.bin文件下载到本地之后,根据dump文件大小调整mat内存,打开mat初始化文件MemoryAnalyzer.ini,将启动内存调整至比dump大的适当大小,例如-Xmx8120m:

  现在开启我们的dump文件分析之路吧。

梳理mat功能

  先通过一张图来了解强大的Eclipse 插件mat的功能菜单:

  第一个菜单i用于概览全局信息,这是最常用的一个菜单。

mat分析大对象

  下面进入本文核心,分析前面下载的dump文件。通过下图中的Open a Heap Dump按钮加载需要分析的本地dump文件,历史浏览版文件会在按钮下方展示。

Getting Started

  在Getting Started Wizard页面勾选Leak Suspects Report,然后,单击Finish输出首份报告:

  这时可以大概看出内存中存在的问题,此处可以初步定位到内存异常的信息,但是具体问题定位还需继续进行分析。overview界面会以饼图的方式显示当前消耗内存最多的几类对象,可以使我们对当前内存消耗有一个直观的印象。但是,除非你的程序内存泄漏特别明显或者你正好在生成hprof文件之前复现了程序的内存泄漏场景,你才可能通过这个界面猜到程序出问题的地方。

Dominator tree

  开始 Dump 分析时,首先应使用 Dominator tree 了解各支配树起点对象所支配内存的大小,进而了解哪几个root对象是 GC 无法释放大内存的原因。

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

  针对非数组类型的对象,Shallow Heap的大小就是对象与它所有的成员变量大小的总和。当然这里面还会包括一些java语言特性的数据存储单元。针对数组类型的对象,Shallow Heap的大小是数组元素对象的大小总和。

  当个别对象支配树的 Retained Heap 很大且存在明显倾斜时,可以重点分析它们的对象支配关系,展开RingBuffer(老铁的代码可能是其他类)的子树进一步定位到问题根因,如下图可看出最终是业务类的 LogData 对象持有的 String字符串过大:

  把鼠标悬浮在截图中选中行上方时,会显示value的具体值,这是 full GC的根源。其实,刚看到RingBuffer时,我们并不确认它是被哪个业务对象引用的,故需要展开子树,查看具体是哪个业务对象。

Histogram

  功能介绍:以直方图的方式来显示当前内存使用情况可能更加适合较为复杂的内存泄漏分析,它默认直接罗列每个类实例的数量和累计内存占比,包括自身内存占用量(Shallow Heap)及支配对象的内存占用量(Retained Heap)。

  它支持按对象数量、Retained Heap、Shallow Heap(默认排序)等指标排序;支持按正则过滤;支持按 package、class loader、super class、class 聚类统计。使用入口:MAT 主界面 → Histogram

  在这里,我们同样可以发现 LogData 对象吃掉了很大内存,当然,还有另外两个对象:

  根据Objects进行排序后可见,业务类LogData存在131072个对象,消耗的内存也比较靠前,SdkSpan和SpanData存在同样的问题,因此这三个类必定存在问题。

使用场景:有些情况下, Dominator tree 无法展现出热点对象(如按 class 聚合也无明显热点对象,此时 Dominator tree 很难做关联分析判断哪类对象占比高),这时可以使用 Histogram 查看所有对象所属类的分布,快速定位占据 Retained Heap 大头的类。

使用技巧:Integer,String 和 Object[] 一般不直接导致内存问题。为更好的组织视图,可以通过 class loader 或 package 分组进一步排查问题。

Leak Suspects

功能介绍:具备自动检测内存泄漏功能,罗列可能存在内存泄漏的问题点。

使用入口:一般当存在明显的内存泄漏时,分析完Dump文件后就会展现,也可以如下图在 MAT 主页找到 Leak Suspects。

使用场景:需要查看引用链条上占用内存较多的可疑对象。这个功能可解决一些基础问题,但复杂的问题往往帮助有限。

举例分析

  下图中 Leak Suspects 视图展现了两个线程支配了绝大部分内存。

  下图是点击上图中 Keywords 中 "Details" ,获取实例到 GC Root 的最短路径、dominator 路径的细信息。

  同样可以发现使用了RingBuffer的业务类创建了很多线程。

小结

  至此本文基于线上full GC 实战案例讲解了 MAT 工具中常用功能的使用方法和适用场景,尤其是各种功能的组合使用,对快速把脉 JVM 内存问题大有裨益。当然,这里介绍的Mat工具使用方法只是冰山一角,有兴趣的老铁们可以继续深挖。

  那么大家对于这件事都是怎么看的呢?欢迎在文章下方留言讨论,三人行必有我师焉!小编会仔仔细细地看每条评论。

Reference

JVM 使用mat分析Dump文件排查大对象解决系统full GC问题的更多相关文章

  1. MAT工具分析Dump文件(大对象定位)

    前段时间线上服务经常发生卡顿,经过排查发现是大对象引起的Fullgc问题,特此记录排查逻辑. 目录 目的 一.获得服务进程 二.生成dump文件 三.下载mat工具 四.使用mat工具导入第二步生成的 ...

  2. WinDbg分析dump文件排查bug

    文章:WinDbg-如何抓取dump文件 命令: cd C:\Windows\System32\inetsrv appcmd list wp 可以查看各个站点的pid

  3. jvm内存快照dump文件太大,怎么分析

    1.场景 通常,使用eclipse的mat图形化工具打开dump的时候都会内存溢出. 对于比较小的dump,eclipse可以打开,但一旦dump文件太大,eclipse就有点束手无策. 这时候怎么办 ...

  4. 使用MAT(Memory Analyzer Tool)工具分析dump文件--转

    原文地址:http://gao-xianglong.iteye.com/blog/2173140?utm_source=tuicool&utm_medium=referral 前言 生产环境中 ...

  5. 本地模拟内存溢出并分析Dump文件

    java Dump文件分析 前言 dump文件是java虚拟机内存在某一时间点的快照文件,一般是.hprof文件,下面自己模拟一下本地内存溢出,生成dump文件,然后通过mat工具分析的过程. 配置虚 ...

  6. JVM jmap dump 分析dump文件 / 如何使用Eclipse MemoryAnalyzer MAT 排查线上问题

    jhat简介 jhat用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言 这个工具并不是想用于应用系统中而是用于"离线" ...

  7. java OOM还在看log日志,兄弟你错的的很严重,正确方式是分析dump文件

    目录 OOM异常--intsmaze 正确姿势dump文件分析--intsmaze 正确的姿势--intsmaze dump丢失打印--intsmaze 哪些内存溢出会产生dump文件--intsma ...

  8. [Java基础] 使用JMAP dump及分析dump文件

    转载:http://blog.csdn.net/kevin_luan/article/details/8447896 http://liulinxia02.blog.163.com/blog/stat ...

  9. 使用JMAP dump及分析dump文件

    查看整个JVM内存状态 jmap -heap [pid]要注意的是在使用CMS GC 情况下,jmap -heap的执行有可能会导致JAVA 进程挂起 查看JVM堆中对象详细占用情况jmap -his ...

  10. WinDbg分析DUMP文件

    1. 如何生成dump文件?     原理:通过SetUnhandledExceptionFilter设置捕获dump的入口,然后通过MiniDumpWriteDump生成dump文件:       ...

随机推荐

  1. 【由技及道】CI/CD的量子纠缠术:Jenkins与Gitea的自动化交响曲【人工智障AI2077的开发日志】

    摘要:当代码提交触发量子涟漪,当构建流水线穿越时空维度--欢迎来到自动化构建的十一维世界.本文记录一个未来AI如何用Jenkins和Gitea搭建量子纠缠式CI/CD管道,让每次代码提交都成为时空交响 ...

  2. Unable to Connect: sPort: 0 C# ServiceStack.Redis 访问 redis

    需求:  对数据库中的不断抓取的文章进行缓存,因此需要定时访问数据,写入缓存中 在捕获到的异常日志发现错误:Unable to Connect: sPort: 0 使用的访问方式是线程池的方式:Poo ...

  3. AXUI前端框架v3版本已经发布,底层完全改写,基于原生技术标准,想走得更远!

    AXUI的v3版本已经发布! AXUI框架已经经历了第一代和第二代的迭代,充分认识到纯CSS和HTML的局限性,也意识到过多手动编写代码会影响用户体验.因此,AXUI的目标是:既满足原生前端的标准,又 ...

  4. mac环境配置本地nfs服务

    前言 在这篇文章中,讲了在Mac端开启NFS服务,并通过NFS协议让其他设备挂载到你的Mac上. 步骤一:增加配置文件 首先,我们需要编辑NFS的配置文件,以便定义哪些目录可以被远程访问. 打开终端, ...

  5. 解决Mac M芯片 Wireshark 运行rvictl -s 后,出现Starting device failed

    前言 mac os big sur 之后,苹果系统的安全性能提升,导致 rvictl -s 创建虚拟网卡失败. $ rvictl -s 000348120-001621w21184C01E boots ...

  6. C#通过FTP获取服务端文件

    一.简介   实际需求是在前端修改了配置文件后,由上位机统一分发给所有设备,因为下位机支持FTP协议,因此选用FTP来实现文件传输功能. 二.准备工作 1.FTP服务搭建 FTP服务端选用FileZi ...

  7. PKI(Public Key Infrastructure,公钥基础设施)常见标准介绍

    ASN.1 - 数据结构描述语言 文件编码格式 DER编码格式 PEM编码格式 证书.密码学Key格式标准 X.509标准 PKCS(公钥加密标准)系列(PKCS#1.PKCS#8.PKCS#12) ...

  8. ASP.NET Session 清除

    // 值为 null,这样对应的 Session 会继续存在,但值为 null Session["UserId"] = null; // 移除指定 Session Session. ...

  9. Zephyr重定向日志打印到USB串口

    nRF52840DK开发板的例程大多数是从硬件串口打印日志,然后硬件串口在开发板上通过Jlink转换为USB串口,最后打印到电脑上. 这里给出通过52840自己的USB串口打印日志的方法. 以zeph ...

  10. PMP学习记录

    本人在2020年12月已经顺利拿到PMP证书. 第一次听说PMP证书是2016年,一个同事说考试通过拿到了PMP证书,当时对PMP不是很了解.也未作深入了解,当时认为俺是做技术的,这个证书没啥用.O( ...