java線上內存溢出問題排查步驟


一般線上遇到比較頭疼的就是OOM內存溢出問題,我們都會先看錯誤日志,如果錯誤日志能夠定位出哪個類對象導致內存溢出,那么我們只需要針對問題修改bug就好。但是很多時候我們單憑日志無法定位出內存溢出問題,那么我們這時候就需要以下操作來定位問題。

1、top下對當前服務器內存有個大致了解

top后 shift+M俺內存占用由大到小排序,RES是此進程實際占用內存,%MEM是占服務器總內存的49.8。

2、利用ps命令查看服務pid

[root@speedyao java]# ps -aux|grep java

 3、利用jstat查看虛擬機gc情況

jstat  -gc:util <vmid>  [<interval> [<count>]

vmid:虛擬機進程號

interval:采樣時間,默認單位是ms

count:采樣條數

[root@speedyao java]# jstat -gcutil 17561 1000 10

 以上命令代表1秒鍾采樣1次,總共采樣10次。

FULL GC明顯大於YOUNG GC次數,並且FULL GC次數很頻繁,說明程序有大內存對象,並且一直無法釋放。

4、生成dump文件,有兩種方式。 一種是利用jmap直接生成dump文件;另一種是利用gcore先生成core文件,再根據core文件利用jmap生成dump文件。

(1)先說第一種,這種比較簡單,使用這種方案的時候請注意:JVM會將整個heap的信息dump寫入到一個文件,heap如果比較大的話,就會導致這個過程比較耗時,並且執行的過程中為了保證dump的信息是可靠的,所以會暫停應用。

[root@speedyao java]# jmap -dump:format=b,file=heap.prof  17561 

 format=b:表示生成二進制類型的dump文件

file=:后面寫的是輸出的dump文件路徑

17561:jvm進程id

 

(2)接下來是第二種。這一種在jmap轉換core文件的時候比較耗時,並且生成的dump文件用mat打開的時候分析結果不太正確,不太好定位問題。所以我建議使用第一種,雖然會造成服務掛起吧,但是結果總歸是正確的。

利用gcore保存服務的內存信息,因為gcore比jmap的dump會快很多,也不對線上服務有大的影響

[root@speedyao java]# gdb -q  --pid=17561

 

 generate-core-file:生成內存對象,生成的文件存儲在當前位置,文件格式pid.core

detach:斷開與進程的連接

quit:退出

利用jmap將gcore文件轉換為java的dump文件,這一步執行的比較慢,可以用nohup執行,以防止誤點Ctrl+C導致退出。

[root@speedyao java]# jmap -dump:format=b,file=heap.prof /usr/bin/java core.17561 

 format=b:表示生成二進制類型的dump文件

file=:后面寫的是輸出的dump文件路徑

/usr/bin/java:java命令路徑,可以通過命令which java 獲取這個路徑

core.17561:表示core文件路徑

 

6、利用MAT(eclipse開發的可以下載eclipse插件,idea開發的可以下載單獨的MAT壓縮包)分析dump文件。當然也可以用jdk自帶的jvisualvm.exe來分析dump文件

上圖是概要,陰影部分就是大內存對象類,點擊選擇 “list Object”、“with incoming references”,就出現下圖。下圖就是這個對象的信息,RunMian 就是map對象所在的類,這樣就能快速定位出哪個類中的哪個對象出現了內存異常。

下圖Histogram這個tab是堆內存占比從大到小排序。 

以上就是內存問題排查的大致步驟。

轉載於:https://blog.csdn.net/u010430495/article/details/87283064?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.control


免責聲明!

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



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