[转帖]发布即巅峰!万字长文: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

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

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

[转帖]Elasticsearch 的 30 个调优最佳实践!

Elasticsearch 的 30 个调优最佳实践! https://zhuanlan.zhihu.com/p/406264041 ES 发布时带有的默认值,可为 es 的开箱即用带来很好的体验。全文搜索、高亮、聚合、索引文档 等功能无需用户修改即可使用,当你更清楚的知道你想如何使用 es 后,你

[转帖]QUIC & HTTP/3 Support:主流浏览器和服务端对 HTTP/3 的支持情况(2021年12月更新)

https://sysin.org/blog/quic-http3-support/ 1. 相关概念 1.1 TLSv1.3 TLS 1.3 由 IETF 于 2018 年 8 月正式发布。 SSL 即 Secure Sockets Layer 安全套接字层。TLS 即 Transport Laye

[转帖]夜莺 监控项目

项目介绍 夜莺监控是一款开源云原生观测分析工具,采用 All-in-One 的设计理念,集数据采集、可视化、监控告警、数据分析于一体,与云原生生态紧密集成,提供开箱即用的企业级监控分析和告警能力。夜莺于 2020 年 3 月 20 日,在 github 上发布 v1 版本,已累计迭代 100 多个版

[转帖]央企信创79号文,全面指导国资信创产业发展

https://baijiahao.baidu.com/s?id=1748464391475464650&wfr=spider&for=pc 信创,即信创产业、信息技术应用创新产业,旨在实现信息技术领域的自主可控,保障国家信息安全。其核心在于通过行业应用拉动构建国产化信息技术软硬件底层架构体系和全周

[转帖]总结:nginx502:Tomcat调优之acceptCount

问题背景:UI页面点击会偶尔返回error,检查调用日志,发现nginx报502报错,因此本文即排查502报错原因。 如下红框可知,访问本机个备机的服务502了,用时3秒左右(可见并不是超时) 先给出原因:是因为tomcat8默认的acceptCount是100,请求量大的时候,会将一些来不及处理的

[转帖]CPU,内存,硬盘,网卡 性能参数

https://zhuanlan.zhihu.com/p/148235895 CPU性能参数 CPU(Central Processing Unit),即中央处理器。CPU从雏形出现到发展壮大的今天,由于制造技术的越来越先进,其集成度越来越高,CPU内部晶体管的数量,虽然从最初的2200多个发展到今

[转帖]RabbitMQ 的重要概念(术语)

Message 消息指的是 RabbitMQ 的队列中保存的数据。 Producer 消息的生产者,即 message publisher(sender),是指负责创建和发送消息的程序。 Vhost RabbitMQ 的虚拟主机,一个 broker 里可以开设多个 vhost,用作不同用户的权限分离

[转帖]发布策略知多少?蓝绿 / 红黑 / 灰度 / 滚动...

https://my.oschina.net/koderover/blog/5608477 随着市场的快速发展,产研团队需要更快迭代需求、更高频发布变更。但由于无法完全模拟线上流量和真实场景,频繁发布可能导致整个系统风险。当出现一个小问题,就可能导致服务的可用性受损、用户体验甚至客户服务受到影响。而