MAT
概述
MAT(Memory Analyzer Tool)工具是一款功能强大的Java堆内存分析器, 可以用于查找内存泄漏以及查看内存消耗情况
MAT是基于Eclipse进行开发的, 不仅可以单独使用, 也可以作为插件的形式嵌入在Eclipse中使用
可以在 官网下载并使用
主要作用就是用来分析Dump文件的
MAT不是一个万能工具, 并不能处理所有类型的堆存储文件, 但是比较主流的如Sun, HP, SAP所采用的的hprof二进制堆存储文件, 已经IBM的PHD堆存储文件等都能被很好的解析
最最重要的功能是可以为开发人员生成内存泄漏报表, 方便定位问题和分析问题
生成Dump文件
file->acquire heap dump -> 选择对应进程即可
MAT介绍
分析Dump文件
histogram
展示各个类的实例数目以及这些实例的shallow heap(浅堆)和retained heap(深堆)的总和
thread overview
- 查看系统中的java进程
- 查看局部变量的信息
对象相互引用关系
浅堆与深堆
- shallow heap(浅堆):
- 只一个对象所消耗的内存, 在32位系统中, 一个对象引用占4个字节, 一个int类型会占据4个字节, long类型占据8个字节, 每个对象头需要占用8个字节, 根据对快照格式不同, 对象的大小可能回想8字节对齐
- 以String为例:
- String类中有两个int变量,占8个字节, 一个对象引用变量占4个字节, 一个对象头占8个字节,总计20字节, 向8字节对齐,最后总大小为24字节(JDK7中)
- 这24字节为String对象的浅堆大小, 与String的value值无关, 无论value的长度如何, 其浅堆始终为24自己
- retained heap(深堆)
- 指对象的保留集中所有的对象的浅堆大小之和
- 保留集:
- 对象A的保留集是指A被垃圾回收后, 可以被释放的所有的对象集合(包括对象A本身), 即对象A的保留集可以被认为是只能通过对象A被直接或间接访问到的所有对象的集合, 就是指对象A所持有的对象的集合
浅堆指对象本身占用的内存, 不包括其内部引用对象的大小, 一个对象的深堆值只能通过该对象访问到的所有对象的浅堆之和,即对象被回收后可以释放的真实空间
对象的实际大小:
对象的实际大小是一个对象所能触及的所有对象的浅堆大小之和, 与深堆并不相同
比如下图中, A.B.C.D.E五个对象, A引用了C.D, B引用看C.E, 那么A的浅堆大小只是A本身, A的实际大小是A.C.D三者之和, A的深堆大小为A.D, 由于C还可以通过B访问到, 所以C并不能算在A的深堆范围之内
支配树
支配树的概念源自于图论
MAT提供了一个称为支配树的对象图, 体现了对象实例间的支配关系, 在对象引用图中所有执行B的路径都经过对象A, 则认为对象A支配对象B, 如果对象A是离对象B最近的一个 支配对象, 则认为对象A为对象B的直接支配者, 支配树是基于对象间的引用图所建立的,具有以下基本特征
- 对象A的子树(所有被对象A支配的对象集合)表示对象A的保留集即深堆
- 如果A支配B,那么A的直接支配者也支配B
- 支配树的边与对象引用图的边不直接对应
JProfiler
概述
JProfiler是ej-technologies公司开发的一款Java应用性能诊断工具, 功能强大, 但是收费
官网地址
- 特点:
- 使用方便,界面操作友好
- 对被分析的应用小
- CPU, Thread, Memory分析功能尤其强大
- 支持对jdbc, noSql, jsp, servlet, socket等进行分析
- 支持多种模式(在线, 离线)分析
- 支持监控本地, 远程的JVM
- 跨平台, 拥有多种操作系统的安装版本
- 主要功能
- 方法调用
- 对方法调用的 分析可以帮助了解应用程序 正在做什么, 并找到提高其性能的方法
- 内存分配
- 通过分析堆上对象, 引用链和垃圾收集可以帮助修复内存泄漏问题, 优化内存使用
- 线程和锁
- 提供多种针对线程和锁的分析视图帮助发现线程问题
- 高级子系统
- 许多性能问题都发生在更高的语义级别上, 例如, 对JDBC的调用, 可以找出执行最慢的SQL语句, JProfiler支持对这些子系统进行集成分析
安装
客户端安装直接去官网下载安装即可
- JProfiler中配置IDEA(11.0版本需要下面的步骤,11.1.4版本的不需要,只需要在IDEA中安装好插件即可)
Session-> IDE Integrations
选择IDEA
点击Integrate-> Proceed
在C:/User下找到IDEA的一个隐藏目录选择
配置完成
- IDEA配置启动JProfiler
IDEA中启动JProfiler只需要在Plugins里面搜索JProfiler安装插件
安装完成后, 在settings->tools-> JProfiler 设置启动JProfilr程序路径
IDEA启动选项会出现如下图标, 需要JProfiler检测时, 使用该启动方式启动即可
使用
两种数据采集方式
- Instrumentation 重构模式
- JProfiler全功能模式, 在class加载之前, JProfiler把相关功能代码写入到需要分析的class的bytecode中.对正在运行的jvm有一定影响
- 优点: 功能强大, 调用的堆栈信息是准确的
- 缺点: 若要分析的 class比较多, 则对应用的性能影响较大, CPU开销可能很高,(取决于Filter的控制), 因此此模式一般配合Filter使用, 只对特定的类或包进行分析
- Sampling 抽样模式
- 类似于样本统计, 每个一定时间(5ms)将每个线程中方法栈中的信息统计出来
- 优点: 对CPU开销非常低, 对应用影响小,
- 缺点: 一些数据不能提供, 如方法的调用次数, 执行时间等
JProfiler本身没有指出数据的采集类型, 这里的采集类型是针对方法调用的采集类型, 因为JProfiler的绝大多数核心功能都依赖于方法调用采集的数据, 所以可以直接认为是JProfiler的数据采集类型
一般情况下选择Sampling 模式就足够了,这个也是推荐使用的模式, 其他不需要做任何调整, 使用默认的就可以了
遥感监测
可以点击左侧去查看各个条目详细情况
内存视图
- All Objects
关注的点:
Size大,数量多->频繁创建的Java对象 -> 死循环, 循环次数过多
Size大,数量不多->存在大的对象-> 读取文件时, byte[] 应该边读边写
存在内存泄漏-> 可以从内存角度查看每次垃圾回收完后的最低点是否成线性关系, 如果是,那么很有可能存在 内存泄漏
之后配合Record Objects进行分析
如果存在一直活跃,且没有被回收过的对象, 那么就很有可能是内存泄漏的原因了
- Record Objects
- Allocation Call Tree
- Allocation Hot Spots
- Class Tracker
堆遍历
可以生成对快照或者对转储文件
CPU视图
线程视图
主要关三个方面:
- web容器的线程最大数, 比如Tomcat的线程容量应该略大于并发数
- 线程阻塞
- 线程死锁
都可以在History中看到
监视器&锁