1. 背景
当你真正去解决fullgc的问题的时候,并不能一概而论的去解决问题,而是要具体分析,掌握具体的命令和监控工具才能根本上解决问题
2. 怎么解决频繁fullGC
频繁fullgc就调整堆的大小,那只是扬汤止沸
如果发生频繁的fullgc,首先要做的就是先看fullgc之后能不能有效的把内存回收掉,同时把堆的快照dump下来,分析一下fullgc的原因, 如果fullgc没有效果,那有可能存在内存泄露,如果fullgc有效,就是堆内存配置不合理,导致老年代很快被塞满了,
确实业务量太大了服务器自身的配置有点扛不住
怎么看fullgc是否生效,主要看老年代内存使用率,fullGC的时间
jstat -gcutil pid
jstat -gc pid
3. 频繁fullGC到底多久一次算频繁
fullgc 是需要STW的,初始标记,重新标记,标记清除是需要STW的,一次FullGc的耗时基本上在1s左右,一般来说一个小时一次就算频繁的了,好一点的应用一天不能超过一次
4. JVM什么情况下会触发FullGC
- System.gc(), 建议JVM fullgc
- 老年代空间不足, 老年代空间只有在新生代对象转入和创建大对象、大数组的时候才会出现老年代空间不足,执行fullgc之后任然不足就会OOM, 调优的时候应该尽量做到让对象在minor gc阶段被回收, 堆中分配很大的对象,大对象就是需要大量连续内存空间的java对象
3,在进行minor gc的时候, survivor 放不下,对象只能放到老年代,而此时老年代也放不下就会造成promotion failed,
- concurrent mode failure 是在执行CMS GC的过程中同时有对象要放入老年代,而此时老年代空间不足导致的
- JVM空间老年代担保机制本:老年代可用空间大小是否大于新生代对象总大小,老年代可用空间是否大于之前每一次Minor GC后进入老年代的对象的平均大小
老年代的内存使用率超过90%,也会触发fullgc,通过参数控制 -XX:CMSInitiatingOccupancyFraction