天天看点

JVM中GC什么时候开始进行

  • 发生区域

    GC一般发生于堆空间中,堆空间主要分Eden和两个survivor区。

  • 堆内存分配

    优先分配到Eden区中,当空间不足时发生Minor GC,大多数对象都是

    朝生夕灭,所以Minnor GC很频繁,速度非常快。

  • Full GC

    发生在老年代,老年代没有空间就会发生,发生之前会执行 一次Minnor GC。大的对象会直接进入老年代,虚拟机会提供一个PretenureSizeThreadhold参数,大于这个直接在老年代分配,避免在新生代来回复制。

  • Minnor GC

    发生时,会判断需要晋升到老年代的大小老年代是否能存下,如果不能存下,则会发生Full GC。如果能存下的话,则查看 HandlePromotionFailure 设置是否允许担保失败,如果允许,那只会进行一次 Minor GC,如果不允许,则改为进行一次 Full GC。

资料显示:

在JDK 6 Update 24之后,HandlePromotionFailure参数不会再影响到虚拟机的空间分配担保策略,观察OpenJDK中的源码变化(见代码清单),虽然源码中还定义了HandlePromotionFailure参数,但是在代码中已经不会再使用它。JDK 6 Update 24之后的规则变为只要老年代的连续空间大于新生代对象总大小或者历次晋升的平均大小就会进行Minor GC,否则将进行Full GC

bool TenuredGeneration::promotion_attempt_is_safe(size_t
max_promotion_in_bytes) const {
   // 老年代最大可用的连续空间
   size_t available = max_contiguous_available();  
   // 每次晋升到老年代的平均大小
   size_t av_promo  = (size_t)gc_stats()->avg_promoted()->padded_average();
   // 老年代可用空间是否大于平均晋升大小,或者老年代可用空间是否大于当此GC时新生代所有对象容量
   bool   res = (available >= av_promo) || (available >=
max_promotion_in_bytes);
  return res;
}