GC悲观策略

GC悲观策略

Posted by CaiJiahe on May 9, 2017

GC悲观策略

Minor GC:只回收年轻代的垃圾。
Full GC:回收包括年轻代老年代永久代在内的java堆空间的垃圾。
GC悲观策略:在Minor GC中,根据年轻代平均晋升大小、年轻代占用空间、老年代空闲空间来判断是否进行一次Full GC。

0x01 为什么需要悲观策略?

  通常情况下MinorGC的时候会将无法存放在suvivor的对象晋升到老年代中去,如果老年代空间无法存放下这些对象会触发一次FullGC,而FullGC中又会对年轻代进行一次MinorGC。因此在这种情况下,一次MinorGC会引发对年轻代的两次回收,悲观策略就是在尽量避免这种情况的发生。

0x02 Parallel GC的悲观策略

PSScavenge是Parallel的年轻代垃圾收集器。

  bool PSScavenge::invoke() {
    // 在年轻代收集失败的时候判断是否进行一次fullgc
    const bool scavenge_done = PSScavenge::invoke_no_policy();
    const bool need_full_gc = !scavenge_done ||
                policy->should_full_GC(heap->old_gen()->free_in_bytes());

    ...

    if (need_full_gc) {
      ...
      if (UseParallelOldGC) {
        full_gc_done = PSParallelCompact::invoke_no_policy(clear_all_softrefs);
      } else {
        full_gc_done = PSMarkSweep::invoke_no_policy(clear_all_softrefs);
      }
    }
    return full_gc_done;
  }

  bool PSScavenge::invoke_no_policy() {
    ...
    if (!should_attempt_scavenge()) {
      return false;
    }
    ...
  }

  bool PSScavenge::should_attempt_scavenge() {
    ...
    size_t avg_promoted = (size_t) policy->padded_average_promoted_in_bytes();
    size_t promotion_estimate = MIN2(avg_promoted, young_gen->used_in_bytes());
    bool result = promotion_estimate < old_gen->free_in_bytes();
    return result;
  }

should_attempt_scavenge中的代码是取出年轻代的平均晋升大小,和当前年轻代的使用空间取最小值,如果这个最小值大于老年代剩余空间,则放弃当前的MinorGC进行一次FullGC。