集合未分页处理导致的full-gc
参考文献:
- 战小狼: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文件。