Hotspot 垃圾回收之DefNewGeneration(二) 源码解析

    目录

1、gc_prologue / gc_epilogue

2、 compute_new_size

3、copy_to_survivor_space

4、 ageTable

5、IsAliveClosure / ScanWeakRefClosure / FastKeepAliveClosure 

6、FastScanClosure / KlassScanClosure / CLDToKlassAndOopClosure / FastEvacuateFollowersClosure

7、collect


本篇博客继续上一篇《Hotspot 垃圾回收之DefNewGeneration(一) 源码解析》讲解DefNewGeneration的GC相关方法的实现。

1、gc_prologue / gc_epilogue

      gc_prologue方法是在GC开始前调用的预处理,gc_epilogue是在GC结束后调用的尾处理,其实现如下:

void DefNewGeneration::gc_prologue(bool full) {
  // Ensure that _end and _soft_end are the same in eden space.
  eden()->set_soft_end(eden()->end());
}

void DefNewGeneration::gc_epilogue(bool full) {
  DEBUG_ONLY(static bool seen_incremental_collection_failed = false;)

  assert(!GC_locker::is_active(), "We should not be executing here");
  GenCollectedHeap* gch = GenCollectedHeap::heap();
  if (full) {
    DEBUG_ONLY(seen_incremental_collection_failed = false;)
    //正常情况下GC结束后eden区是空的,如果非空说明堆内存满了,eden区中的存活对象未拷贝至老年代中
    if (!collection_attempt_is_safe() && !_eden_space->is_empty()) {
      if (Verbose && PrintGCDetails) {
        gclog_or_tty->print("DefNewEpilogue: cause(%s), full, not safe, set_failed, set_alloc_from, clear_seen",
                            GCCause::to_string(gch->gc_cause()));
      }
      //通知GCH promote事变
      gch->set_incremental_collection_failed(); // Slight lie: a full gc left us in that state
      //允许使用from区分配对象
      set_should_allocate_from_space(); // we seem to be running out of space
    } else {
      if (Verbose && PrintGCDetails) {
        gclog_or_tty->print("DefNewEpilogue: cause(%s), full, safe, clear_failed, clear_alloc_from, clear_seen",
                            GCCause::to_string(gch->gc_cause()));
      }
      gch->clear_incremental_collection_failed(); // We just did a full collection
      clear_should_allocate_from_space(); // if set
    }
  } else {

  }

  if (ZapUnusedHeapArea) {
    //mangle三个区
    eden()->check_mangled_unused_area_complete();
    from()->check_mangled_unused_area_complete();
    to()->check_mangled_unused_area_complete();
  }

  if (!CleanChunkPoolAsync) {
    //清空ChunkPool
    Chunk::clean_chunk_pool();
  }

  //更新计数器
  update_counters();
  gch->collector_policy()->counters()->update_counters();
}

//该方法返回尝试回收垃圾是否是安全的
bool DefNewGeneration::collection_attempt_is_safe() {
  if (!to()->is_empty()) {
    if (Verbose && PrintGCDetails) {
      gclog_or_tty->print(" :: to is not empty :: ");
    }
    //如果to区非空则返回false,正常都是空的
    return false;
  }
  if (_next_gen == NULL) {
    //初始化_next_gen,DefNewGeneration第一次准备垃圾回收前_next_gen一直为null
    GenCollectedHeap* gch = GenCollectedHeap::heap();
    _next_gen = gch->next_gen(this);
  }
  //判断next_gen是否有充足的空间,允许年轻代的对象复制到老年代中
  return _next_gen->promotion_attempt_is_safe(used());
}

两者的调用链如下:

2、 compute_new_size

       compute_new_size用于在GC结束后根据老年代的大小和NewRatio,NewSizeThreadIncrease两个参数重新计算年轻代的大小,并做适当的扩容或者缩容处理。

void DefNewGeneration::compute_new_size() {
  //正常from区或者to区在GC结束后都是空的,如果非空则说明堆内存已满
  if (!from()->is_empty() || !to()->is_empty()) {
    return;
  }

  int next_level = level() + 1;
  GenCollectedHeap* gch = GenCollectedHeap::heap();
  assert(next_level < gch->_n_gens,
         "DefNewGeneration cannot be an oldest gen");

  Generation* next_gen = gch->_gens[next_level];
  size_t old_size = next_gen->capacity();
  size_t new_size_before = _virtual_space.committed_size();
  size_t min_new_size = spec()->init_size();
  size_t max_new_size = reserved().byte_size();
  assert(min_new_size <= new_size_before &&
         new_size_before <= max_new_size,
         "just checking");
  size_t alignment = Generation::GenGrain;

  // 计算年轻代新的大小,基于NewRatio和NewSizeThreadIncrease
  size_t desired_new_size = old_size/NewRatio;
  //获取非后台线程数
  int threads_count = Threads::number_of_non_daemon_threads();
  //NewSizeThreadIncrease表示每个非后台线程增加的年轻代的内存大小,默认是4k
  size_t thread_increase_size = threads_count * NewSizeThreadIncrease;
  desired_new_size = align_size_up(desired_new_size + thread_increase_size, alignment);

  // Adjust new generation size
  desired_new_size = MAX2(MIN2(desired_new_size, max_new_size), min_new_size);
  assert(desired_new_size <= max_new_size, "just checking");

  bool changed = false;
  if (desired_new_size > new_size_before) {
    //如果大于原来的,则需要扩容
    size_t change = desired_new_size - new_size_before;
    assert(change % alignment == 0, "just checking");
    //尝试扩容指定大小的内存
    if (expand(change)) {
       //扩容成功,置为true
       changed = true;
    }
  }
  if (desired_new_size < new_size_before && eden()->is_empty()) {
    //则eden区是空的情形下才允许缩容,非空的条件下缩容有可能导致对象丢失
    size_t change = new_size_before - desired_new_size;
    assert(change % alignment == 0, "just checking");
    _virtual_space.shrink_by(change);
    changed = true;
  }
  if (changed) {
    //如果改变,则重新计算三个区的内存边界并初始化,compute_space_boundaries方法会保证eden区的内存足够大
    compute_space_boundaries(eden()->used(),
                             SpaceDecorator::Clear,
                             SpaceDecorator::DontMangle);
    MemRegion cmr((HeapWord*)_virtual_space.low(),
                  (HeapWord*)_virtual_space.high());
    //重置bs对应的覆盖区域              
    Universe::heap()->barrier_set()->resize_covered_region(cmr);
    if (Verbose && PrintGC) {
      size_t new_size_after  = _virtual_space.committed_size();
      size_t eden_size_after = eden()->capacity();
      size_t survivor_size_after = from()->capacity();
      gclog_or_tty->print("New generation size " SIZE_FORMAT "K->"
        SIZE_FORMAT "K [eden="
        SIZE_FORMAT "K,survivor=" SIZE_FORMAT "K]",
        new_size_before/K, new_size_after/K,
        eden_size_after/K, survivor_size_after/K);
      if (WizardMode) {
        gclog_or_tty->print("[allowed " SIZE_FORMAT "K extra for %d threads]",
          thread_increase_size/K, threads_count);
      }
      gclog_or_tty->cr();
    }
  }
}

GenerationSpec* Generation::spec() {
  GenCollectedHeap* gch = GenCollectedHeap::heap();
  assert(0 <= level() && level() < gch->_n_gens, "Bad gen level");
  return gch->_gen_specs[level()];
}

MemRegion reserved() const { return _reserved; }

bool DefNewGeneration::expand(size_t bytes) {
  MutexLocker x(ExpandHeap_lock);
  HeapWord* prev_high = (HeapWord*) _virtual_space.high();
  //尝试扩容指定大小的内存
  bool success = _virtual_space.expand_by(bytes);
  if (success && ZapUnusedHeapArea) {
    //扩容成功,执行mangle操作
    HeapWord* new_high = (HeapWord*) _virtual_space.high();
    MemRegion mangle_region(prev_high, new_high);
    SpaceMangler::mangle_region(mangle_region);
  }

  if (GC_locker::is_active()) {
    if (PrintGC && Verbose) {
      gclog_or_tty->print_cr("Garbage collection disabled, "
        "expanded heap instead");
    }
  }

  return success;
}

其调用链如下:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值