一、 內存溢出問題的排查
1. 使用工具 - jdk自帶
- jmap
- visualvm
2. 流程
- 堆轉儲:
(1) 方法一:程序運行時,采用:jmap -dump:format=b,file=d:\\data\\xxlJob.hprof 23300
進行堆文件的轉儲
(2) 方法二:在內存溢出的時候,打印堆轉儲文件
-XX:+HeapDumpOnOutOfMemoryError # 開啟OOM時自動轉儲堆
-XX:HeapDumpPath=/path/to/dump/dir/ # 指定堆轉儲文件路徑
-XX:OnOutOfMemoryError="command args" # OOM時執行外部命令
- 導入visualVM中
文件->裝入->選擇堆轉儲文件
- 分析:自定義的對象的數量、大小都不應該太大
a. 通過大小、對象數量進行排序,查看靠前的對象是否存在自定義的對象
b. 通過名稱排序,查看自定義的對象中,哪個對象最靠前
二、gc頻繁問題的排查
1. 了解堆分配的策略
a. 優先分配到年輕代
b. 大對象直接分配到老年代
c. 長期存活的對象進入老年代
d. 對象擔保策略:如果年輕代的對象的總容量大于了老年代的剩余容量,需要進行一次full gc
2. 頻繁minor gc
原因
(1) 內存分配過小
(2) 內存泄漏
(3) 頻繁的對象創建
排查和解決方案
(1)經過mimor gc之后,對象仍舊無法被清除,導致full gc:考慮內存泄漏問題,查看是否存在內存泄漏,可以通過jmap + visualvm進行排查
(2) 如果是并發高的場景:minor gc之后,考慮eden分配過小,嘗試增大內存的分配量,尤其是eden區的
(3) 如果不是高并發,內存還有急速升高的情況,可能是對象創建太過頻繁,或者創建了大對象導致的
總結:分配大內存 + 排查堆轉儲文件,查看哪個自定義對象的占用內存較大,優化代碼
3. 頻繁full gc
原因
(1)minor gc分配太小,導致頻繁minor gc,進而對象年齡急速增加,進入老年代
(2)full gc 分配太小,空間擔保機制,使得minor gc之前,需要進行full gc
(3)內存泄漏或者大對象的創建
解決方案:
(1)首先嘗試分配大內存
(2)如果不行,通過排查堆轉儲文件,也就是使用jmap和visualvm查看較大的自定義對象