注:如果你的程序運行很久,積累大量的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飈高。