mac下 内存分析工具mat安装,使用mat分析:内存溢出、内存泄漏,结合jstat、jmap等命令的使用

分析前提:

  • mat的安装详情:mac下安装 mat内存分析工具_MissNull的博客-CSDN博客_mac mat下载
                                使用Eclipse Memory Analyzer Tool(MAT)分析线上故障(一) - 视图&功能篇 - Trust_FreeDom - 博客园
  • 安装后,再具体使用过程中,发现我dump的文件有4个G,而mat默认的配置是1个G,因此需要修改默认配置,修改流程如下:mac下MAT打开大hprof文件报错的解决_freshfishfish的博客-CSDN博客
  • jps命令查询进程号
  • jmap -histo pid | head -n20     查看TOP20对象分布,这个直接展示在屏幕上,也可打印到文件 jmap -histo:live [pid] >a.log

  • jstat -gc pid 3000:每隔三秒打印一次gc信息,运行结果中:
    O:old代已使用的占当前容量百分比 ,

    YGC:从应用程序启动到采样时年轻代中gc次数         

    YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)         

    FGC:从应用程序启动到采样时old代(全gc)gc次数         

    FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)         

    GCT:从应用程序启动到采样时gc用的总时间(s)    

  • jmap -dump:format=b,file=/home/admin/logs/heap.hprof pid      dump出系统的堆栈详情,便于用mat工具分析

  • 匿名内部类的含义

  • Spring创建的实例,默认都是单例的

真实的代码实例不方便展示给大家,这里写一个简单的demo,方便大家感知下使用了内部类的一些问题:

//定义一个Sping的服务,有个test方法,作用就是往list里面add线程
@Component
public class MonitorServiceImpl implements MonitorService {

    private static List<Runnable> list = new ArrayList<>();

    @Override public void test(final GnssDeviceListInfo info) {
        list.add(new Runnable() {
            @Override public void run() {
                info.getDeviceType();
            }
        });
    }
}
//test方法就是往List队列中加线程任务(new Runnable这种写法就是匿名内部类)


//模拟一个不断调用该服务方法的restful接口,方便用Postman调用:
@GetMapping("/test")
public  queryAllInServiceDevice(){
    while(true){
       Thread.sleep(1);
       monitorService.test(new GnssDeviceListInfo());
    }
}

项目启动后调用/test,就会触发test服务方法,运行一段时间后,发现系统非正常运行了,可以有很多指标,这里不说了,我们直接分析:

第0步:jps命名找服务进程号

第一步:观测GC信息

执行命名jstat -gccause 24203 3000,观测gc,发现:

 

第二步:用jmap命令打印出前30个耗费资源最多的对象:

这个例子写的太简单,直接可以看出来,假设我们看不出来,需要使用mat工具来排查,需要先dump实时的堆栈信息:

第三步:获取dump堆栈:jmap -dump:format=b,file=/Users/chao.zheng/heap.hprof 24203
第四步:根据mat分析生成的heap.hprof 文件:

分析第一个problem suspect 1

点击这个案例,用树形结构展示,方便看:

发现MonitorServiceImpl创建了大量的实例(其实上面的jmap -histo命令直接就可以看出来了(这里只是为了演示一些操作,读者可不必在意啊),有接近100万个对象创建出来了,这不是与大家掌握的知识:Spring默认是单例的有冲突嘛)

分析总结:

  1. Spring中的服务默认是单例的,这句话无可厚非
  2. 例子中的list.add(new Runnable()),会不断的创建线程任务到list中,因为写法是new Runnable(),实际就会创建一个匿名内部类(如何判断的呢,MonitorServiceImpl$1,看这个字符串末尾的$1就代表是内部类的标志)
  3. 如果没有线程及时的去处理list中的任务,就会导致list中的任务越来越多,如果还没有限制List的容量大小,最终会导致占用的内存越来越多,观察gc信息也可以发现,fullgc越来越频繁,系统几乎一直在fullgc,导致系统几乎Hung死

由于示范的例子不是很好,可能无法很好的去描述问题,有疑问欢迎留言~

或者直接点击这个按钮:

可能这个对象最多的不一定占用内存最大,但我们知道java是引用的,可能他引用的对象超级多、大,可以进一步慢慢分析

MAT其他判断标准:

  • 分析 Unreachable:重点看一下这个,关注下 Shallow 和 Retained 的大小。如下图所示,笔者之前一次 GC 优化,就根据 Unreachable Objects 发现了 Hystrix 的滑动窗口问题。
    MAT默认不开启,需要自己打开:

     

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值