集合未分頁處理導致的full-gc
阿新 • • 發佈:2018-12-05
參考文獻:
- 戰小狼:OMG!又一個頻繁FullGC的案例;
- jdk8下進行的,jdk11不存在此案例問題。
1. 問題
集合持有的x物件不能被young-gc
,從而晉升到old區導致full-gc
。因此可以設定閾值在年輕代佔滿之前釋放掉x物件——可被young-gc
掉。
- 錯誤程式碼
for(int i=0;i<bigNum;i++){ List<ObjectX> globalList = ArrayList(); for(int j=0;j<bigNumber;j++){ ObjectX obj=new ObjectX(); globalList.add(obj); } //處理連結串列物件資料 dealWithList(golbalList); }
- 如果
bigNumber
或bigNum
夠大,會導致globalList
持有過多的物件引用——這些物件對不能被gc回收,發生以下情況會導致頻繁的full-gc
:物件過多、年輕帶被佔滿,未達到年齡的物件不斷晉升到老年代,老年代被佔用到一定比例時會發生頻繁的full-gc
。如果每一次外迴圈globalList
持有的物件太多則會直接導致記憶體溢位。
2.解決辦法
將程式碼修改為:
int thresHold=500; for(int i=0;i<bigNum;i++){ List<ObjectX> objList = ArrayList(); for(int j=0;j<bigNumber;j++){ ObjectX obj=new ObjectX(); objList.add(obj); /** *此時年輕代已經存有thresHold*n個物件, *為防止年輕代被佔滿,應該及時處理物件,並清理連結串列中 *物件引用,讓這些物件可以被young-gc掉 */ if(objList.size()>thresHold){ dealWithList(golbalList); objList.clear(); } } //處理連結串列物件資料 dealWithList(golbalList); }
3. 其他:分析問題可能用到的命令和工具
//為了儘快復原問題可以設定以下引數
-Xmx400m:最大堆記憶體;
-Xms400m:初始化堆記憶體;
-Xmn150m:年輕代大小;
-verbose:gc:verbose.a冗長的;輸出GC詳情;
-XX:+PrintGCDetails:輸出GC資訊;
-XX:+HeapDumpBeforeFullGC:在Full gc之前dump堆檔案
jstat -gcutil vmId x_millionSecond
實時列印記憶體區佔用情況;- visualVM:可用於分析dump檔案。