Java分析工具MemoryAnalyzer和JStack的使用,定位服务器内存飚高和CPU飚高的问题

注:如果你的程序运行很久,积累大量的dump信息,这个时候你使用jmap很有可能会直接把你的程序卡死,所以jmap这个命令不适合线上使用,在进行测试和压测的时候使用比较好。在线上环境,慎用jmap。

内存飙高:

1.在官网下载MemoryAnalyzer:https://www.eclipse.org/mat/

2.创建一个java测试程序mat-test,写如下代码:

public class CarModel {
    public boolean run()
    {
        try {
            Thread.sleep(5000);
            System.out.println(Thread.currentThread().getName()+"  "+new Date().toString());
            return true;
        }
        catch(Exception ex)
        {
            return false;
        }
    }
}

public class App {
    public static void main(String[] args) {
        System.out.println("start:");
        ExecutorService executor = Executors.newCachedThreadPool();
        for (int i = 0; i < 5000; i++) {
            try {
                Thread.sleep(1000);
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        new CarModel().run();
                    }
                });
            } catch (Exception ex) {

            }
        }
        executor.shutdown();
        startWhile();
        System.out.println("end");
    }

    private static void startWhile() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) ;
            }
        }).start();
    }
}

3.打包,部署到服务器,这里我使用的是docker部署的,如果你不知道如何用docker部署,请参考我的另外一篇博客:https://blog.csdn.net/dap769815768/article/details/86561566

4.启动容器后,使用

docker exec -it mat-test /bin/bash

进入到容器内。使用

ps -ef |grep java

查看这个容器里面你的java程序运行的pid。使用jmap命令:

jmap -dump:file=test.dump 1

到处dump文件,这里的1是我的程序的pid。

5.成功后,按ctr+d,退出容器,使用命令:

docker cp mat-test:test.dump ./test.dump

将容器内生成的dump文件导出Linux环境,然后下载到本地。

6.打开MemoryAnalyzer,file=》open heap dump,选择Leak Suspects Report,打开之后默认显示界面如下:

7.选择Overview=》Unreachable Objects Histogram,可以查看到类被实例化的数量:

8.在default_report选下卡里面,有具体的统计信息,可以看到我们这个例子中,统计信息总共分成三部分:

紧接着下面就是Problem的具体描述:

点击Details可以查看详细内容。这里不再深入探讨。

CPU飙高:

我们的这个例子有一个死循环,这会导致cpu飚高,如果是内存飚高,刚才的方式是可以清晰地看到具体哪些东西占用了内存。但是看不到cpu被占用的情况,要看cpu占用的情况,需要使用jstack这个工具。

1.首先进到我们的Linux服务器,使用top命令查看cpu使用情况

这里的java程序cpu占用率始终在99%以上,我们知道,之所以这么高,是因为我们故意写了一个死循环导致的。

2.使用docker exec -it mat-test /bin/bash进入到容器里面,使用jstack命令看看在容器内部占用cpu高的是哪个进程,找到进程pid。

在容器内部,这个进程的id是1。

3.使用top -Hp 1,可以查询到具体是哪个线程占用cpu高:

可以看到是pid为15的线程cpu占用偏高。

4.使用jstack 1,查看具体信息:

如果你还记得刚才的那个线程id,你就会发现,这里标注的16进制数字转过来正好是15,没错,也就是在代码的第14行的一个run方法里面,有大量的cpu占用。这个run方法里面的内容,就是我们写的死循环。

好了,到这里,cpu飚高的问题就定位到具体的代码位置了,下面就是找到具体的代码,分析出现飚高的原因了,这个例子里,代码很好分析,就是因为死循环,而实际上大部分场景下,可能都没那么好分析,比如有些网络请求阻塞了而又没有去设置网络请求等待超时时间,这样等待时间就会无限长,积攒久了,也可能会导致cpu飚高。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值