这篇文章想记录下Java的GC的一些细节,例如什么时候JVM会垃圾回收?
哪些对象将会被回收?还会讨论下哪些对象会进入到老年代。
注意: 你需要先知道 Eden/Old/Minor gc/Full gc/S0 S1这些都代表什么
- Eden 年轻代中的一部分,年轻代 * 80%
- S0 年轻代中的一部分,年轻代 * 10%
- S1 年轻代中的一部分,年轻代 * 10%
- Old 年老代
- Minor gc 针对年轻代的垃圾回收,快,程序不会暂停
- Full gc 针对年老代的垃圾回收,慢,程序会暂停,俗称 Stop The World
如果对上述概念没有深刻的理解,来看一张图,加深印象
GC的几种时机:
- Eden满了Minor gc
- 升到老年代的对象大于老年代剩余空间Full gc,小于时被HandlePromotionFailure参数强制Full gc (看注意事项,JDK1.7之后有变化)promontion failed:
- Eden + S0 满,复制到S1,S1也不足,转而复制到Old Gen,如果Old Gen也不足,就会产生promontion failed,从而产生Full Gc
- 大对象在Eden区放不下,就会直接放到old ,old放不下触发Full Gc
- 现在反射很多,Permanet Generation中存放的为一些class的信息、常量、静态变量等数据,可能会导致java.lang.OutOfMemoryError: PermGen space
JVM对象进入老年代的4种情况:
- 假如进行Minor GC时发现,存活的对象在ToSpace区中存不下,那么把存活的对象存入老年代
- 大对象直接进入老年代
- 长期存活的对象将进入老年代
年轻代每从from复制到to一次,增加1岁,默认15岁之后,会进入老年代,配置参数-XX:MaxTenuringThreshold可以调整
进入老年代的最大年龄 - 动态对象年龄判定
如果在From空间中,相同年龄所有对象的大小总和大于From和To空间总和的一半,那么年龄大于等于该年龄的对象就会被移动到老年代,而不用等到15岁(默认):
-XX:HandlePromotionFailure=false
this is invalid since JDK1.7 and later version
JDK1.7 之后,变更为:
老年代的空间足够容纳下sum(新生代)或avg(历次晋升),就minor gc OR full gc
全文完。