[转帖]发布即巅峰!万字长文:Java性能调优六大工具:MAT内存分析工具

发布,巅峰,字长,java,性能,六大,工具,mat,内存,分析 · 浏览次数 : 0

小编点评

**文章标题:Java性能调优六大工具解析** **文章简介:** 文章介绍了Java性能调优六大工具,包括MAT内存分析工具。MAT是基于Eclipse开发平台的产品,可以用于对内存使用率进行分析。文章展示了如何使用MAT进行内存分析,以及如何分析内存使用率的字符串对象。 **MAT内存分析工具简介:** MAT是一种基于Eclipse开发平台的内存分析工具,可以用于对内存使用率进行分析。MAT可以用于对内存使用率进行分析,以及如何分析内存使用率的字符串对象。 **MAT分析工具的用法:** 1. 安装MAT程序及Eclipse开发工具。 2. 创建一个插件工程。 3. 添加插件的扩展点。 4. 在实际开发中,选择合适的扩展点增强MAT的功能。 5. 对插件进行打包。 **MAT分析工具的优势:** * 可以对内存使用率进行分析。 * 可以分析内存使用率的字符串对象。 * 可以根据内存使用率进行性能优化。 **文章结论:** 文章介绍了Java性能调优六大工具,包括MAT内存分析工具。MAT是基于Eclipse开发平台的内存分析工具,可以用于对内存使用率进行分析。文章展示了如何使用MAT进行内存分析,以及如何分析内存使用率的字符串对象。

正文

jianshu.com/p/4ed3dd8b7b83

 

MAT是MemoryAnalyzerTool的简称,它是一款功能强大的Java堆内存分析器,可以用于查找内存泄漏以及查看内存消耗情况。MAT是

基于Eclipse开发的一款免费的性能分析工具,读者可以在
http://www.eclipse.org/mat/上下载并使用MAT。

一,初识MAT

在分析堆快照前,首先需要导出应用程序的堆快照。在本书前文中提到的jmap、JConsole和VisualVM等工具都可以用于获得Java应用程序的堆快照文件。此外,MAT本身也具有这个功能。

如图6.66所示,在File菜单中选择AcquireHeapDump命令,在弹出对话框的当前Java应用程序列表中选择要分析的应用程序即可,如图6.67所示。

 
image.png
 
image.png

除了直接在MAT中导出正在运行的应用程序堆快照外,也可以通过File菜单中的OpenHeapDump命令打开一个既存的堆快照文件。

注意:使用MAT既可以打开一个已有的堆快照,也可以直接从活动Java程序中导出堆快照。

图6.68所示为正常打开堆快照文件后的MAT界面。

 
image.png

在图6.68的右侧界面中显示了堆快照文件的大小、类、实例和ClassLoader的总数;饼图中显示了当前堆快照中最大的对象。将光标悬停在饼图中,可以在左侧的Inspector界面中查看该对象的详细信息。在饼图中单击,可以对选中的对象进行更多的操作。

单击工具栏上的柱状图按钮(如图6.69所示),可以查看当前堆的类信息,包括类的对象数量、浅堆(Shallow)大小和深堆(Retained)大小,如图6.70所示。

 
image.png

通过柱状图界面,可以查找引用选中对象的对象集合以及选中对象所引用的对象集合。如图6.71所示,选中java.util.Vector对象并右击,在弹出的右键菜单中选择Listobjects命令,弹出的withoutgoingreferences和withincomingreferences子命令分别表示查找java.util.Vector实例的引用对象,以及引用java.util.Vector实例的对象。

 
image.png

注意:通过MAT,可以根据对象间的引用关系对内存中的对象进行分析。

图6.72显示了选择withincomingreferences命令后的输出结果,展示了两个被主线程引用的java.util.Vector局部变量实例。

为了方便查看,柱状图还可以根据ClassLoader和包对类进行排序。图6.73显示了MAT的柱状图排序功能,以及一个按照包进行排序的柱状图输出命令。

 
image.png

图6.72 引用关系查询结果

 
image.png

二,浅堆和深堆

浅堆(ShallowHeap)和深堆(RetainedHeap)是两个非常重要的概念,它们分别表示一个对象结构所占用的内存大小和一个对象被执行GC操作后,可以真实释放的内存大小。

浅堆是指一个对象所消耗的内存。在32位系统中,一个对象引用会占据4个字节,一个int类型会占据4个字节,long型变量会占据8个字节,每个对象头需要占用8个字节。

根据堆快照格式不同,对象的大小可能会向8字节进行对齐。以String对象为例,图6.74显示了String对象的几个属性。

3个int类型以及一个引用类型合计占用的内存为3×4+4=16字节,再加上对象头的8个字节,因此String对象占用的空间,即浅堆的大小是16+8=24字节。浅堆的大小只与对象的结构有关,与对象的实际内容无关。也就是说,无论字符串的长度是多少,内容是什么,浅堆的大小始终是24字节。

 
image.png

深堆的概念略微复杂。要理解深堆,首先需要了解保留集(RetainedSet)。对象A的保留集指当对象A被垃圾回收后,可以被释放的所有的对象集合(包括对象A本身),即对象A的保留集可以被认为是只能通过对象A被直接或者间接访问到的所有对象的集合。通俗地说,就是指仅被对象A所持有的对象的集合。深堆是指对象的保留集中所有对象的浅堆之和。

注意:浅堆指对象本身占用的内存,不包括其内部引用对象的大小。一个对象的深堆指只能通过该对象访问到的(直接或间接)所有对象的浅堆之和,即对象被回收后,可以释放的真实空间。

下面这个例子很好地诠释了深堆的概念。首先是表示点的类定义:

 
image.png

接着是表示线的类定义:

 
image.png

主函数构造了a、b、c、d、e、f、g这7个点,以及aLine、bLine、cLine和dLine这4条线,并在程序最后将a、b、c、d、e这5个点设置为null。具体代码如下:

 
image.png

这段代码的对象引用关系如图6.75所示,其中a、b、c、d、e对象在使用完成后被设置为null。

 
image.png

根据Point类的结构,一个Point实例的浅堆大小为4×2+8=16字节,一个Line实例的浅堆大小为4×2+8=16字节。使用MAT得到该示例的内存快照文件,如图6.76所示。为了阅读方便,笔者将代码中的变量名标识到了内存快照中的对象上。

 
image.png

可以看到,所有的Point实例浅堆和深堆的大小都是16字节。而dLine对象,浅堆为16字节,深堆也是16字节,这是因为dLine对象内的两个点f和g没有被设置为null,因此即使dLine被回收,f和g也不会被释放。对象cLine内的引用对象d和e由于仅在cLine内还存在引用,因此只要cLine被释放,d和e必然也作为垃圾被回收,即d和e在cLine的保留集内,因此cLine的深堆为16×2+16=48字节。

对于aLine和bLine对象,由于两者均持有对方的一个点,因此当aLine被回收时,公共点a在bLine中依然有引用存在,故不会被回收,点a不在aLine对象的保留集中,因此aLine的深堆大小为16+16=32字节。对象bLine与aLine完全一致。

在MAT中,无论是在柱状图还是对象列表中,选中对象并右击,在弹出的快捷菜单中都有ShowRetainedSet命令,它可用于显示指定类或者对象的保留集。图6.77和图6.78分别为在bLine对象上进行该操作,以及bLine对象的保留集。

 
image.png
 
image.png

三,支配树

MAT提供了一个称为支配树(DominatorTree)的对象图。支配树体现了对象实例间的支配关系。在对象引用图中,所有指向对象B的路径都经过对象A,则认为对象A支配对象B。如果对象A是离对象B最近的一个支配对象,则认为对象A为对象B的直接支配者。支配树是基于对象间的引用图所建立的,它具有以下基本性质:

·对象A的子树(所有被对象A支配的对象集合)表示对象A的保留集(retainedset)。

·如果对象A支配对象B,那么对象A的直接支配者也支配对象B。

·支配树的边与对象引用图的边不直接对应。

如图6.79所示,左图表示对象引用图,右图表示左图所对应的支配树。对象A和B由根对象直接支配,由于在到对象C的路径中可以经过A,也可以经过B,因此对象C的直接支配者也是根对象。对象F与对象D相互引用,因为到对象F的所有路径必然经过对象D,因此对象D是对象F的直接支配者。而到对象D的所有路径中,必然经过对象C,即使是从对象F到对象D的引用,从根节点出发,也是经过对象C的,所以对象D的直接支配者为对象C。

 
image.png

同理,对象E支配对象G。到达对象H的路径可以通过对象D,也可以通过对象E,因此对象D和E都不能支配对象H,而经过对象C既可以到达D也可以达到E,因此对象C为对象H的直接支配者。

在MAT中,单击工具栏上的对象支配树按钮,如图6.80所示,可以打开对象支配树视图。

 
image.png

图6.81显示了对象支配树视图的一部分。该截图显示部分main线程对象的直接支配对象,即main线程对象被回收后将被释放的所有对象的集合。

注意:在对象支配树中,某一个对象的子树表示在该对象被回收后也将被回收的对象的集合。

 
image.png

四,垃圾回收根

在Java系统中,作为垃圾回收的根节点可能是以下对象之一。

·系统类:被
bootstrap/systemClassLoader加载的类,例如在rt.jar包中的所有类。

·JNI局部变量:本地代码中的局部变量,例如用户自定义的JNI代码或者JVM内部代码。

·JNI全局变量:本地代码中的全局变量。

·线程:开始,并且没有停止的线程。

·在用同步锁:作为锁的对象。例如调用了wait()或者notify()方法的对象,或者调用了synchronized(Object)操作的对象。

·Java局部变量:如函数的输入参数及方法中的局部变量。

·本地栈:本地代码中的输入、输出参数,例如用户自定义的JNI代码或者JVM内部代码。

·Finalizer:在等待队列中将要被执行析构函数的对象。

·Unfinalized:拥有析构函数,但是没有被析构且不在析构队列中的对象。

·不可达对象:从任何一个根对象都无法到达的对象。但为了能够在MAT中分析,被MAT标志为根。

·未知对象:未知的根类型,用于处理一些特殊的堆格式。

通过MAT,可以列出所有的根对象,如图6.82所示。

 
image.png

五,内存泄漏检测

MAT提供了自动检测内存泄漏,以及统计堆快照内对象分布情况的工具。图6.83展示了内存泄漏检测工具的使用方法。选择菜单中的LeakSuspects命令,MAT会自动生成一份报告。这份报告罗列了系统内可能存在内存泄漏的问题点。图6.84展示了报告中给出的一个问题点样例。

 
image.png

注意:仔细阅读MAT给出的内存泄漏报告,可以帮助开发人员更快地找到系统的潜在问题。

 
image.png

六,最大对象报告

系统中占用内存最大的几个对象,往往是解决系统性能问题的关键所在。如果应用程序发生内存泄漏,那么泄漏的对象通常会在堆快照中占据很大的比重。因此,查看和分析堆快照中最大的对象具有较高的价值。

在MAT中,可以自动查找并显示消耗内存最多的几个对象。如图6.85所示,通过选择TopConsumers命令,可以打开消耗内存最多的对象的报告,其中主要以饼图和表格的形式来展示。

 
image.png

七,查找支配者

通过MAT,开发人员还可以很方便地查找某一个对象或者类的支配者(有关支配者的概念,可以参考6.7.3节“支配树”)。虽然在支配树页面中拥有完整的信息,但是通过MAT提供的支配者查找功能可以更方便地进行查找。图6.86显示了如何查找对象的支配者。

 
image.png

在选择ImmediateDominators命令后,会弹出一个参数对话框,用于设置查找参数,如图6.87所示。在参数对话框中,注意务必正确输入-skip参数,否则查询结果会忽略所有定义在-skip参数中的类和实例。

ImmediateDominators会输出选中对象的直接支配者(将-skip指定的对象排除在外)。

 
image.png

八,线程分析

在堆快照中,还包括当前的线程信息,通过MAT可以查看这些信息。如图6.88所示,通过ThreadDetails、ThreadOverview和ThreadStacks这3个命令,可以查看线程详情。

 
image.png

图6.89所示为选择ThreadStacks命令后的输出结果,其中显示了当前堆快照中的所有线程及线程引用的对象。

 
image.png

九,集合使用情况分析

MAT提供了一套对集合使用状态进行分析的工具,如图6.90所示。

 
image.png

使用这些工具,可以查看数组、集合的填充率;可以观察集合内的数据;也可以分析哈希表的冲突率。

注意:通过对集合使用情况进行分析,可以更好地了解系统的内存使用情况,查找浪费的内存空间。

选择CollectionFillRatio命令,可以展示给定集合的填充率。图6.91所示为该功能的输出结果,其中显示了填充率为0、20%以下、80%以下和100%以下的集合个数。

 
image.png

通过选择HashEntries命令,可以查看Hash表的内容。图6.92所示为该功能的一个输出示例,其中显示了选中的Hash表的内容。对于表中的Key和Value对象,通过右键快捷菜单,还可以进一步分析它们的引用情况和其他具体信息。

 
image.png

十,扩展MAT

MAT是基于Eclipse开发平台的产品,因此它也具有很好的扩展性。开发者可以使用Eclipse对MAT进行扩展,从而实现符合开发人员需要的功能更加强劲的内存分析工具。通过扩展MAT,读者可以实现诸如自动对象查询、优化界面显示、报表增强等功能。本节将通过一个简单的MAT插件,介绍扩展MAT的基本步骤和方法。

注意:MAT是基于Eclipse的,因此对MAT进行二次开发与开发Eclipse插件非常类似。

在Java中,java.lang.String对象实现是基于内部的value字符数组、偏移量offset和字符串长度count来定义字符串String的真实取值的。如果内部数组value的实际长度很长,而字符串真实长度count的数值很小,则说明这个String的内存使用率不高,存在较为严重的内存浪费。

使用公式count/value.length可以计算当前String对象的内存使用率。在最优情况下,String对象的内存使用率是100%,即表示value数组中的所有字符都是当前字符串的内容。当使用类似String.subString()的函数生成新的字符串时,String对象通过调整offset和count,而非创建新的value数组来生成新的字符串,此时String对象的内存利用率就会下降。

本节中展示的插件将在显示String对象时,展示String对象的内存利用率,帮助开发者快速定位可以优化的字符串对象。

为扩展MAT,首先需要安装MAT程序及Eclipse开发工具。

(1)在Eclipse平台中添加MAT目标平台。在Eclipse中打开对话框:Windows|Preferences|Plug-inDevelopment|TargetPlatform。添加MAT平台,选择Add|Nothing|Next。在目标平台的Locations页面中,添加Installation,并指定MAT的安装路径,如图6.93所示。单击Finish按钮,并选择刚刚添加的MAT平台作为目标平台。图6.94所示为配置完成后的目标平台。

 
image.png

(2)创建一个插件工程。选择File|New|Other|Plug-inproject命令,假设工程名称是MATExtension,其他参数可以使用默认设置。创建完成后,在工程的Dependencies页面中添加org.eclipse.mat.api依赖,如图6.95所示。

 
image.png
 
image.png

(3)添加插件的扩展点。在本例中添加
org.eclipse.mat.api.nameResolver,如图6.96所示。在实际开发中,读者可以根据自己的需要,选择合适的扩展点增强MAT的功能。接着填写扩展点的具体信息,如实现扩展点接口的类名和包名,Eclipse会自动生成指定的类,如图6.97所示。

 
image.png
 
image.png

编辑生成的StringUsageDisplayer类,具体代码如下:

 
image.png

StringUsageDisplayer的功能是当MAT中显示String对象时,计算String对象的count值与value数组的长度比值。注释@Subject指定当前
IClassSpecificNameResolver只对java.lang.String对象有效。

(4)当完成开发后,还需要对插件进行打包。选择File|Export|Plug-inDevelopment|
Deployableplug-insandfragments命令,在打开的对话框中选中要打包的插件,并设置MAT的安装路径进行插件安装,如图6.98所示。

安装完成后,在MAT的plugins目录下就有了MATExtension插件的JAR包。

安装插件后的MAT,可以使用以下OQL查询取得所有内存利用率不是100%的String。

 
image.png

查询结果如图6.99所示,其中不仅显示了字符串的真实取值,也显示了当前字符串的内存使用率,可以帮助开发人员快速定位能够优化的字符串。

注意:通过对MAT的扩展,可以让MAT更贴近实际生产环境,使之更易于使用,提高了堆内存分析的效率。

 
image.png
 
image.png

本文给大家讲解的内容是Java性能调优六大工具:MAT内存分析工具

 
 
0人点赞
 
日记本
 
 

与[转帖]发布即巅峰!万字长文:Java性能调优六大工具:MAT内存分析工具相似的内容:

[转帖]发布即巅峰!万字长文:Java性能调优六大工具:MAT内存分析工具

jianshu.com/p/4ed3dd8b7b83 MAT是MemoryAnalyzerTool的简称,它是一款功能强大的Java堆内存分析器,可以用于查找内存泄漏以及查看内存消耗情况。MAT是 基于Eclipse开发的一款免费的性能分析工具,读者可以在http://www.eclipse.org

[转帖]飞腾发布新一代桌面级处理器腾锐D2000,使用14nm工艺制造

https://baijiahao.baidu.com/s?id=1688392509052524770&wfr=spider&for=pc S2500的供货是一个问题啊. 近日,国内芯片设计厂商天津飞腾发布了新一代桌面级处理器腾锐D2000。关心国内处理器的除了国人,国外的群众也没少看相关消息,连

[转帖]【Redis系列】Redis发布版本历史及特性

目录 概述Redis2.6Redis2.8Redis3.0Redis3.2Redis4.0Redis5.0Redis6.0Redis7.0 概述 Redis 使用标准版本标记进行版本控制:major.minor.patchlevel。 偶数的版本号表示稳定的版本, 例如 1.2,2.0,2.2,2.

[转帖]阿里发布自研ARM服务器芯片倚天710,不对外出售

https://www.modb.pro/db/139440 10月19日,阿里巴巴旗下半导体公司平头哥发布自研云芯片倚天710,并宣称该芯片是业界性能最强的ARM服务器芯片,性能超过业界标杆20%,并且,能效也高出业内标杆50%以上。 业界标杆是谁呢?目之所及,从目前云厂商的ARM处理器而言,最成

[转帖]英特尔正式发布第四代Xeon至强可扩展处理器,Intel7工艺;i9-13900KS首秀,开箱即用六个G

https://new.qq.com/rain/a/20230111A06IFM00 11 日消息,英特尔今日正式发布了第四代至强可扩展处理器(代号 Sapphire Rapids)和至强 CPU Max 系列(代号 Sapphire Rapids HBM),以及英特尔数据中心 GPU Max 系列

[转帖]7大openGauss商业版发布,共推规模落地行业核心场景

神舟通用、云和恩墨、超图软件、南大通用、海量数据、超聚变及中国联通 https://baijiahao.baidu.com/s?id=1738417443151957787&wfr=spider&for=pc 央广网北京7月15日消息 openGauss Developer Day 2022(ope

[转帖]大话云原生之灰度发布篇 - 从步行到坐缆车的自动化服务升级

https://xie.infoq.cn/article/9b22d0ca95e7d48748bb0a5fd 看过很多关于云原生的文章,要么云山雾罩,要么曲高和寡。 所以笔者就有了写《大话云原生》系列文章的想法,期望用最通俗、简单的语言、方便记忆的场景来说明:云原生生态系统内的组成及应用关系。 一、

[转帖]Intel“革命性”X86s架构,带来哪些颠覆及影响?

https://www.eet-china.com/mp/a221822.html 英特尔发布了一份新的白皮书(Intel X86-S扩展架构规格),计划简化其处理器指令集架构(ISA)。英特尔提供了“x86-S”的ISA(指令集架构),其中“S”可能代表“简化”。它是当前 x86-64 ISA 的

[转帖]chrome历史版本及重大变化(维基百科)

Google Chrome是Google LLC开发的免费 网络浏览器。开发过程分为不同的“发布渠道”,每个发布渠道都在单独的开发阶段进行构建。Chrome提供了4种渠道:稳定版,测试版,开发版和金丝雀。在稳定版本上,Chrome对于次要版本每两到三周更新一次,对于主要版本每六周更新一次。[1] 下

[转帖]从代工厂看先进制程

https://m.thepaper.cn/baijiahao_16445399 台积电已于近日发布了2021年第四季度财报。数据显示,台积电7nm及以下制程贡献营收达到一半。其在先进制程的发力可见一斑。魏哲家还预计,台积电将于2025年推出2nm芯片。 业界普遍将7nm及以下制程归为先进制程,目前