鉴于现在各种gc名称已经叫混了,首先声明一下minor gc和full gc的定义:
minor gc: 回收区域只包括年轻代即eden, from, to。
full gc: 回收区域包括新生代,老年代和元空间。
注:有的人把major gc和full gc混为一谈,我更愿意认为major gc等价于old gc,目前只有cms收集器存在只回收老年代的情况。
minor gc触发条件:
- eden空间不足。
- system.gc()在触发full gc之前会先发生minor gc。
full gc触发条件:
- 大对象直接进入老年代时老年代空间不足
- 年轻代对象经过minor gc晋升老年代老年代空间不足
-
在发生minor gc之前虚拟机将会检查老年代剩余空间是否大于新生代对象总空间(考虑最坏情况,新生代所有对象都晋升),如果条件成立,那么可以确保这次minor gc是安全的。否则,虚拟机会虚拟机参数HandlePromotionFailure的设置值是够允许冒险(允许:-XX:+HandlePromotionFailure,不允许:-XX:-HandlePromotionFailure)。如果允许那么虚拟机会查看老年代剩余空间是否大于历次晋升老年代对象大小的平均值,当老年代剩余空间大于历次晋升大小平均值时虚拟机将冒险进行一次minor gc,如果当前minor gc晋升对象的大小总和远超历史平均值老年代接不下的话将导致空间分配担保失败,从而再执行一次full gc;如果老年代空间小于历次晋升平均值或者-XX:HandlePromotionFailure不允许冒险都将放弃minor gc改为full gc。JDK 6 UPDATE 24以后HandlePromotionFailure参数失效了,JDK1.8中已经没有了这个参数,改为只要老年代连续空间总大小大于历次晋升平均大小就进行minor gc,否则进行full gc。(相当于默认为真了) - 方法区空间不足,jdk1.8使用元空间实现方法区一般很难出现这种情况了。
- cms垃圾收集器发生concurrent mode failure后将暂停用户线程,启用Serial Old垃圾收集器进行full gc。
- g1垃圾收集器收集时当收集速度赶不上内存分配速度,也会触发串行垃圾收集器进行full gc作为担保机制。
- 调用System.gc()方法作为建议jvm执行full gc的条件,不保证执行