一次老生代內存使用占比飆升問題解決


一次老生代內存使用占比飆升問題解決

老生代內存使用占比圖示

 

如圖所示老生代內存占比不斷增加,超過80%系統自動報警,之前的解決方案是手動重啟😜。

 

1、保存現場

為了解決上面老生代問題,首先需要dump下堆文件

命令:

ps -ef|grep DialingRobot

 

 DialingRobot是服務名稱,找到對應的pid

 

pid:70992

dump堆內存

jmap -dump:format=b,file=1.dump 70992

將堆內存dump下來

為了分析內存的變化,可以在不同的時間進行dump操作,可以分析前后的內存變化,更方便查找問題

2、分析問題

 

 1、jprofiler分析dump文件

將文件重命名為20200520.hprof(.hprof是可以分析的堆文件)

 

 

 打開后長這樣

可以去看一下biggest對象

 

 

 

 

 

 

點開之后發現,占有內存比較大是正常的,這些類里面都存放着大量的內存緩存。

 

 

 

第二考慮是不是這個類太多了,沒有釋放,分析兩個時間段的堆內存,兩個dump中的這個對象的數量大小差異不大。嘗試mat去分析下dump文件。

 2、mat分析dump文件

 

 

 主要使用兩個模塊:Histogram和LeakSuspects

Histogram主要展示堆內的各個對象的大小

 

 

將兩個hprof文件導入mat,可以使用比較去分析兩個內存的前后的變化

 

 

 兩個hprof文件前后對象的差異、內存的差異

 

 分析這些差異,沒有看到什么有用的信息。

嘗試使用第二個mat的工具:Leak Suspects

 

 

mat給出兩個suspect,可以分析下,第一個還是之前的class文件過大,但是是由於內部維護了一部分緩存造成的,第二個cs csSocket也不是,跟JProfiler差異不大。

 

這個時候分析到達一個比較艱難的時候。

這個時候查看下jvm的參數設置:

 

可以看出來整個堆的大小是:1g,新生代是256mb,老年代是1024-256=768mb,看上去沒有什么問題。

這個時候需要分析我們的應用,我們的應用中的對象的特征,我們應用中的對象很少有需要一直存在的對象,更多是朝生夕死的對象,這樣的話,這個的是不是有問題呢?

我們去看看新生代的內存、回收情況。

 

可以看出來,老生代內存使用率的增加和新生代的gc強相關,新生代gc一次,老生代的內存使用率升高一點

 

3、解決問題

修改jvm參數

 

 

將堆內存從1g->2g,新生代256m->1024m,觀察老生代情況。

 

可以看出來:老生代內存使用占比穩定,新生代回收頻率也降低了很多(13 -> 3 /30min),單次耗時:(10ms -> 20ms),30分鍾內gc時間從130ms -> 60ms,降低了一倍

 由此可見,服務中存在大量短期臨時對象,擴容新生代空間后,Minor GC頻率降低,對象在新生代得到充分回收,只有生命周期長的對象才進入老年代。這樣老年代增速變慢,Major GC頻率自然也會降低。


免責聲明!

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



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