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飈高。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章