GC 持续时间 Garbage Collection 上的平均时间是每分钟 5 分钟。 警告阈值:30.00%。
原因 垃圾回收时间超过系统设置的时间阈值,
这就需要了解下什么时候触发GC ,为什么会GC
Young GC----针对年轻代
当Eden区满了的时候,会触发Young GC
Full GC----针对整个堆
1. 在发生Young GC的时候,虚拟机会检测之前每次晋升到老年代的平均大小是否大于年老代的剩余空间,如果大于,则直接进行Full GC;
2. 如果小于,但设置了Handle PromotionFailure,那么也会执行Full GC。promotion failed是在进行Minor GC时,survivor space放不下、对象只能放入老年代,而此时老年代也放不下造成的。
3. 永久代空间不足,会触发Full GC
4. System.gc()也会触发Full GC
5. 堆中分配很大的对象
所谓大对象,是指需要大量连续内存空间的java对象,例如很长的数组,此种对象会直接进入老年代,而老年代虽然有很大的剩余空间,但是无法找到足够大的连续空间来分配给当前对象,此种情况就会触发JVM进行Full GC。为了解决这个问题,CMS垃圾收集器提供了一个可配置的参数,即-XX:+UseCMSCompactAtFullCollection开关参数,用于在“享受”完Full GC服务之后额外免费赠送一个碎片整理的过程,内存整理的过程无法并发的,空间碎片问题没有了,但提顿时间不得不变长了,JVM设计者们还提供了另外一个参数 -XX:CMSFullGCsBeforeCompaction,这个参数用于设置在执行多少次不压缩的Full GC后,跟着来一次带压缩的。
6. CMS GC concurrent mode failure
concurrent mode failure是在执行CMS GC的过程中同时有对象要放入老年代,而此时老年代空间不足造成的(有时候“空间不足”是CMS GC时当前的浮动垃圾过多导致暂时性的空间不足触发Full GC)。
简单理解: 当 survivor space放不下时,会放到老年代里, 当老年代也放不下时就触发了 full GC
解决办法
full GC的根本原因是内存不足,导致老年代没有足够的内存接收对象,最简单的办法是加大JAVA 堆内存,
其次是优化 JVM
参考案例
通用法则1:
将java堆的初始值-Xms和最大值-Xmx设置为老年代活跃数据大小的3~4倍
所以此处就设置 -Xms1600m,-Xmx1600m
在以上的测试结果中可以看到原始的堆大小为1675m左右,是比较接近的。
通用法则2:
永久带的初始值-XX:PermSize及最大值-XX:MaxPermSize应该比永久代活跃数据大1.2~1.5倍
所以此处就设置-XX:PermSize=13m,-XX:MaxPermSize=13m
补充法则:
新生代空间应该为老年代空间活跃数据的1~1.5倍
此处老年代为400m,新生代就为600m
如果java堆的初始值及最大值为活跃数据的3~4倍,新生代为活跃数据的1~1.5倍时,老年代应设置为活跃数据大小的2~3倍
参考表