java full gc引发的问题


问题现象:线上无结果报警,rein的cost高,rein下游java模块cost正常。

这里先讲一下java的分代回收,效果图如下:

1.绝大多数刚创建的对象会被分配在Eden区,其中的大多数对象很快就会消亡。当Eden区满的时候,执行Minor GC,将消亡的对象

清理掉,并将剩余的对象复制到一个存活区Survivor0(此时,Survivor1是空白的,两个Survivor总有一个是空白的;此后,每次Eden

区满了,就执行一次Minor GC,并将剩余的对象都添加到Survivor0;当Survivor0也满的时候,将其中仍然活着的对象直接复制到

Survivor1,以后Eden区执行Minor GC后,就将剩余的对象添加Survivor1(此时,Survivor0是空白的)。

2.在年轻代中经历了N次回收后仍然没有被清除的对象,会被放到年老代中,在老年代内存被占满时触发Full GC,回收整个堆内存。

3.持久代:用于存放静态文件,比如java类、方法等。持久代对垃圾回收没有显著的影响。、

每次 Minor GC 会清理年轻代的内存

Major GC 是清理老年代,searchhub用的cms gc,过程包括:

?初始标记(STW initial mark)----- Stop The Word

?并发标记(Concurrent marking)

?并发预清理(Concurrent precleaning)

?重新标记(STW remark)----- Stop The Word

?并发清理(Concurrent sweeping)

?并发重置(Concurrent reset)

Full GC 是清理整个堆空间—包括年轻代和老年代。

触发最初现象的原因是:java模块在cms gc的时候出现了promotion failed,导致java模块终止程序了30s

总结:CMS GC时出现promotion failed和concurrent mode failure

对于采用CMS进行旧生代GC的程序而言,尤其要注意GC日志中是否有promotion failed和concurrent mode failure两种状况,

当这两种状况出现时可能会触发Full GC。

promotion failed是在进行Minor GC时,survivor space放不下、对象只能放入旧生代,而此时旧生代也放不下造成的;

concurrent mode failure是在执行CMS GC的过程中同时有对象要放入旧生代,而此时旧生代空间不足造成的