除直接调用System.gc外,触发Full GC执行的情况有如下四种:
1、老年代空间不足
老年代空间只有在新生代对象转入及创建为大对象、大数组时才会出现不足现象,当执行Full GC后空间仍然不足,则抛出 java.lang.OutOfMemoryError:Java heap space
2、Permanet Generation 空间满
Permanet Generation 中存放的为一些class信息,当系统中要加载的类、反射的类和调用的方法较多时,Permanet Generation可能会被占满,在未配置为采用CMS GC的情况下会执行Full GC。如果经过Full GC仍然回收不了,那么JVM会抛出 java.lang.OutOfMemoryError:PermGen space
3、CMS GC时出现promotion failed 和 concurrent mode failure
对于采用CMS进行老年代GC的程序,尤其要注意GC日志中是否有 promotion failed 和 concurrent model failure 两种状况,当这两种状况出现时可能会触发Full GC。 promotion failed是在进行MinorGC时,survivor space放不下、对象只能放入老年代,而此时老年代也放不下造成的;concurrent mode failure是在执行CMS GC的过程中同时有对象放入老年代,而此时老年代空间不足造成的。应对措施:增大survivor space、老年代空间或调低触发并发GC的比率,但在JDK5.0+、JDK6.0+的版本中有可能会由于JDK的bug导致CMS在remark完毕后很久才触发sweeping动作。对于这种状况,可通过设置-XX:CMSMaxAbortablePrecleanTime=5(单位ms)来避免
※什么时候会出现 concurrent mode failure 呢?
因为CMS垃圾收集器用的是标记清除算法,所以再一次次的GC后内存会出现很多的碎片空间,虽然老年代本来有100M的空间,但是连一个10M的对象都放不下。这个时候就会出现 concurrent mode failure。然后系统会执行空间整理操作。但是CMS GC在这种情况下
的整理操作耗时会比并行的GC高很多。对于 concurrent mode failure 的详细说明可以参数 Oracle 工程是写的 《Understanding CMS GC Logs》
4、统计得到的MinorGC晋升到老年代的平均大小大于老年代的剩余空间
这是一个较为复杂的触发情况,Hotspot为了避免由于新生代对象晋升到老年代导致老年代空间不足的现象,在进行MinorGC时,做了一个判断,如果之前统计所得到的MinorGC晋升到老年代平均大小大于老年代的剩余空间,那么就直接出发Full GC。
Minor GC 针对新生代GC
Major GC 针对老年代GC
Full GC 针对永久代、新生代、老年代三者的GC
参考:
【1】微信,http://mp.weixin.qq.com/s?__biz=MzI4NDY5Mjc1Mg==&mid=2247484042&idx=1&sn=51d2ed451151be872b601007597dd47f&chksm=ebf6daf5dc8153e3a7cb88ca97621cfae5aeaaeec0a1ff63e16278fbea6a43457e50a7fc9f0b&scene=21#wechat_redirect