性能分析 | Java服務器內存過高&CPU過高問題排查


一、內存過高

1、內存過高一般有兩種情況:內存溢出和內存泄漏

(1)內存溢出:程序分配的內存超出物理機的內存大小,導致無法繼續分配內存,出現OOM報錯

(2)內存泄漏:不再使用的對象一直占據着內存不釋放,導致這塊內存浪費掉,久而久之,內存泄漏的對象堆積起來,也會導致物理機的內存被耗盡,出現OOM報錯

2、內存過高的檢測辦法:通常我們的Java服務器部署在Linux機器上面,可以通過jvm自帶的命令進行一些檢測

(1)查看對象的數目和占用內存大小

①參數為Java程序的進程號,將結果導出到指定目錄中,

jmap -histo:live <進程號> > <導出目錄+文件名>


②示例如下,可以看到程序中各個對象所占用內存的情況,根據占用字節數大小降序顯示,這里只能看出哪些對象占用內存高,但是還不能具體定位到問題代碼,需要進一步排查

③一些特殊的標識的含義

[C 表示char[],一般與String對象相關,因為String其實就是基於char數組實現的

[S 表示short[]

[I 表示int[]

[B 表示byte[]

[II 表示int[][]

num #instances #bytes class name 
----------------------------------------------
1: 585152 75635896 [C
2: 66541 71446496 [B
3: 1141734 36535488 java.util.HashMap$Entry
4: 176622 26086840 <constMethodKlass>
5: 176622 24034208 <methodKlass>
6: 17717 19584560 <constantPoolKlass>
7: 174454 18375128 [Ljava.util.HashMap$Entry;
8: 571222 13709328 java.lang.String
9: 832783 13324528 java.lang.Integer
10: 17717 13198840 <instanceKlassKlass>
11: 15092 11237440 <constantPoolCacheKlass>
12: 46779 10429728 [I
13: 191501 7660040 java.util.LinkedHashMap$Entry
14: 12599 6567592 <methodDataKlass>
15: 113526 6357456 java.util.HashMap
16: 197998 6335936 java.util.Hashtable$Entry


(2)如果需要進一步定位問題代碼,那么就需要把Java程序的內存鏡像導出,再具體分析了,通過如下命令導出程序的內存鏡像

jmap -dump:format=b,file=<導出目錄+文件名> <進程號> 


(3)下載Memory Analyzer工具來分析內存鏡像

http://www.eclipse.org/mat/ 


(4)打開軟件后,File-->Open Heap Dump...,打開剛才導出的鏡像文件,選擇Leak Suspects Report,Finish,進入分析頁面

Histogram:列表展示出內存中的對象數目和占用內存大小

Dominator Tree:列表展示出程序中每個線程中的對象數目和占用內存大小

Top Consumers:圖表展示出每個線程的對象數目和占用內存大小

Top Components:圖表展示出內存中的對象數目和占用內存大小

Leak Suspects:這個是最常用的,會自動檢測分析內存異常的原因

右鍵對象-->show objects by class可以查看對象的具體情況

by incomming reference:顯示引用該對象/線程的其他對象

by outgoing reference:顯示當前對象/線程引用的其他對象

Java服務器內存過高&CPU過高問題排查


(5)點擊Leak Suspects,程序會分析出可能存在內存問題的地方,繼續點擊Detail可以看到具體有哪些對象和線程,接下來就要根據具體情況具體分析了

二、CPU過高

1、當程序發現CPU過高的情況時,可以使用Windows系統的Process Explorer工具來找到CPU高消耗的線程,所以需要在Windows機器上面搭建好服務器的測試環境,盡量模擬出線上CPU飆升的情況

2、模擬好環境后,通過任務管理器,在進程一欄中找到Java程序的進程號

Java服務器內存過高&CPU過高問題排查


3、下載Process Explorer工具

https://docs.microsoft.com/zh-cn/sysinternals/downloads/process-explorer 


4、打開工具后,根據剛才的進程號找到進程

Java服務器內存過高&CPU過高問題排查


5、然后右鍵-->Properties,再選擇Threads選項卡,點進CPU排序,可以找到消耗CPU最多的那個線程

Java服務器內存過高&CPU過高問題排查


6、使用科學計算器,將十進制的線程號轉成十六進制,比如493620-->78834

Java服務器內存過高&CPU過高問題排查


7、到此已經拿到了可能出問題的進程號和線程號,接下來使用jvm內置的命令來導出Java的堆棧信息

jstack -l <進程號> > <導出目錄+文件名> 


8、打開導出的堆棧信息,並全文搜索剛剛拿到的十六進制的線程號,就可以找到出問題的代碼具體位置了


*版權聲明:轉載文章和圖片均來自公開網絡,版權歸作者本人所有,推送文章除非無法確認,都會注明作者和來源。如出處有誤或侵犯到原作者權益,請與我們聯系刪除或授權事宜,感謝原作者。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM