背景
线上服务频繁Full GC,每次full gc就会有接口超时问题,引起系统告警,曲线图大概如下
老年代内存回收锯齿状。
原因分析
oldgen频繁full gc,先想到的是因为oldgen区域过小吗,调整大以后发现问题依旧没有解决。
我想到的第二个原因:Eden区过小,因为小Eden区域yong gc就会很频繁,这还不是引起Full gc的原因,熟悉gc算法的知道,Young GC 采用的是复制算法,会伴随这对象年龄晋升,如果遇到大对象,或者Eden区过小,就会导致直接把大对象抛到old区,old区一满,就会触发full gc,但是每次full gc完成,old又回到了x轴最低处,因为Eden区过小,old很快又塞满,所以我们看到gc的曲线是锯齿状。
是因为本来old区域的对象就这么多吗?显然不是,因为full gc过后,内存明显变大,显然old里面的对象都是垃圾,是从Eden区过来的。
解决办法
扩大Eden区,调整-Xmn的值,缩小oldgen区域,因为old用不了那么多,大概就是常驻对象的三倍左右,比如,我的工程每次full gc 后,old常驻对象就是400m,那old给1.2G大小,剩下全给Eden。
源码
uint ageTable::compute_tenurin