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

    目录

一、Generation

1、定义

2、is_in / space_containing

3、block_start / block_size / block_is_obj

4、 oop_iterate / object_iterate / safe_object_iterate

5、 prepare_for_compaction / adjust_pointers / compact

二、DefNewGeneration

1、构造函数 / ref_processor_init

2、supports_tlab_allocation / tlab_capacity / tlab_used / unsafe_max_tlab_alloc

3、object_iterate / space_iterate

4、should_allocate /allocate / par_allocate /  expand_and_allocate

 5、oop_since_save_marks_iterate

 6、contribute_scratch / reset_scratch


DefNewGeneration是UseParNewGC为false时(该属性默认为false)的年轻代的实现,包含Eden,From和To三个子内存区,下面来详细讲解DefNewGeneration的定义与实现细节。

一、Generation

1、定义

    Generation表示分代内存中的一个“代”对应的内存区域,是各种分代内存实现的抽象类,其类继承关系如下:

我们重点关注默认配置下CMS算法使用的表示年轻代的DefNewGeneration和表示支持自适应调整堆内存大小的老年代的ASConcurrentMarkSweepGeneration类及其相关类的实现。Generation的定义在hotspot\src\share\vm\memory\generation.hpp中,其包含的属性如下:

  • jlong _time_of_last_gc; //记录上一次GC的发生时间
  • MemRegion _prev_used_region; //在GC过程中的某个特殊时点使用的,用于记录某个值
  • MemRegion _reserved; //为当前Generation保留的一段连续的内存地址空间,注意不能跟其他的Generation的地址空间有交叉
  • VirtualSpace _virtual_space; //同上
  • int _level; //当前Generation在类继承关系中的级别
  • ReferenceProcessor* _ref_processor; //用于处理Reference实例的处理器
  • CollectorCounters* _gc_counters; //用于GC性能跟踪
  • GCStats* _gc_stats; //收集GC的统计数据
  • StatRecord _stat_record; //用于GC性能跟踪

Generation定义了一个枚举Name来描述各子类,其定义如下:

MarkSweepCompact就是上面类继承关系中的TenuredGeneration,可以通过kind方法获取当前Generation实例的类型,其默认实现如下:

重点关注以下方法的实现。

2、is_in / space_containing

      is_in判断某个地址是否在当前Generation已分配的内存空间内,底层调用的是Space::is_in方法,space_containing找到包含指定地址的Space实例,底层调用的是Space::is_in_reserved方法,两方法的实现如下:

bool Generation::is_in(const void* p) const {
  GenerationIsInClosure blk(p);
  //Generation可能包含多个Space实例,space_iterate方法会遍历所有的Space
  ((Generation*)this)->space_iterate(&blk);
  return blk.sp != NULL;
}

class GenerationIsInClosure : public SpaceClosure {
 public:
  const void* _p;
  Space* sp;
  virtual void do_space(Space* s) {
    if (sp == NULL) {
      if (s->is_in(_p)) sp = s;
    }
  }
  GenerationIsInClosure(const void* p) : _p(p), sp(NULL) {}
};

Space* Generation::space_containing(const void* p) const {
  GenerationIsInReservedClosure blk(p);
  // Cast away const
  ((Generation*)this)->space_iterate(&blk);
  return blk.sp;
}

class GenerationIsInReservedClosure : public SpaceClosure {
 public:
  const void* _p;
  Space* sp;
  virtual void do_space(Space* s) {
    if (sp == NULL) {
      if (s->is_in_reserved(_p)) sp = s;
    }
  }
  GenerationIsInReservedClosure(const void* p) : _p(p), sp(NULL) {}
};

 两方法的调用链如下:

3、block_start / block_size / block_is_obj

     这三个方法的实现跟上面的is_in是一致的,都是借助space_iterate和Space的底层方法实现的,分别用于获取指定地址对应的内存块的起始地址和内存大小,指定地址处是否是一个对象。

HeapWord* Generation::block_start(const void* p) const {
  GenerationBlockStartClosure blk(p);
  // Cast away const
  ((Generation*)this)->space_iterate(&blk);
  return blk._start;
}

class GenerationBlockStartClosure : public SpaceClosure {
 public:
  const void* _p;
  HeapWord* _start;
  virtual void do_space(Space* s) {
    if (_start == NULL && s->is_in_reserved(_p)) {
      _start = s->block_start(_p);
    }
  }
  GenerationBlockStartClosure(const void* p) { _p = p; _start = NULL; }
};

size_t Generation::block_size(const HeapWord* p) const {
  GenerationBlockSizeClosure blk(p);
  // Cast away const
  ((Generation*)this)->space_iterate(&blk);
  assert(blk.size > 0, "seems reasonable");
  return blk.size;
}

class GenerationBlockSizeClosure : public SpaceClosure {
 public:
  const HeapWord* _p;
  size_t size;
  virtual void do_space(Space* s) {
    if (size == 0 && s->is_in_reserved(_p)) {
      size = s->block_size(_p);
    }
  }
  GenerationBlockSizeClosure(const HeapWord* p) { _p = p; size = 0; }
};

bool Generation::block_is_obj(const HeapWord* p) const {
  GenerationBlockIsObjClosure blk(p);
  // Cast away const
  ((Generation*)this)->space_iterate(&blk);
  return blk.is_obj;
}

class GenerationBlockIsObjClosure : public SpaceClosure {
 public:
  const HeapWord* _p;
  bool is_obj;
  virtual void do_space(Space* s) {
    if (!is_obj && s->is_in_reserved(_p)) {
      is_obj |= s->block_is_obj(_p);
    }
  }
  GenerationBlockIsObjClosure(const HeapWord* p) { _p = p; is_obj = false; }
};

 

4、 oop_iterate / object_iterate / safe_object_iterate

       实际机制一样,分别用于遍历当前Generation中已分配的Java对象所引用的其他Java对象和遍历Generation中已分配的Java对象,后面两个方法的功能基本一致,其实现如下:

void Generation::oop_iterate(ExtendedOopClosure* cl) {
  GenerationOopIterateClosure blk(cl);
  space_iterate(&blk);
}

class GenerationOopIterateClosure : public SpaceClosure {
 public:
  ExtendedOopClosure* _cl;
  virtual void do_space(Space* s) {
    s->oop_iterate(_cl);
  }
  GenerationOopIterateClosure(ExtendedOopClosure* cl) :
    _cl(cl) {}
};

void Generation::object_iterate(ObjectClosure* cl) {
  GenerationObjIterateClosure blk(cl);
  space_iterate(&blk);
}

class GenerationObjIterateClosure : public SpaceClosure {
 private:
  ObjectClosure* _cl;
 public:
  virtual void do_space(Space* s) {
    s->object_iterate(_cl);
  }
  GenerationObjIterateClosure(ObjectClosure* cl) : _cl(cl) {}
};

void Generation::safe_object_iterate(ObjectClosure* cl) {
  GenerationSafeObjIterateClosure blk(cl);
  space_iterate(&blk);
}

class GenerationSafeObjIterateClosure : public SpaceClosure {
 private:
  ObjectClosure* _cl;
 public:
  virtual void do_space(Space* s) {
    s->safe_object_iterate(_cl);
  }
  GenerationSafeObjIterateClosure(ObjectClosure* cl) : _cl(cl) {}
};

其调用链如下:

5、 prepare_for_compaction / adjust_pointers / compact

      实现基本同上,分别执行compaction的准备工作,计算移动的目标地址并写入对象头中;调整所有引用了需要被移动的对象的引用地址,使其指向新地址;从对象头中获取目标地址,执行对象复制,实现如下:

void Generation::prepare_for_compaction(CompactPoint* cp) {
  //循环遍历所有的Space
  CompactibleSpace* space = first_compaction_space();
  while (space != NULL) {
    //调用prepare_for_compaction方法
    space->prepare_for_compaction(cp);
    space = space->next_compaction_space();
  }
}

void Generation::adjust_pointers() {
  AdjustPointersClosure blk;
  space_iterate(&blk, true);
}

class AdjustPointersClosure: public SpaceClosure {
 public:
  void do_space(Space* sp) {
    sp->adjust_pointers();
  }
};


void Generation::compact() {
  CompactibleSpace* sp = first_compaction_space();
  while (sp != NULL) {
    sp->compact();
    sp = sp->next_compaction_space();
  }
}

其调用链如下:

二、DefNewGeneration

     DefNewGeneration继承自Generation,其定义在同目录下的defNewGeneration.hpp中,增加了如下属性:

  • Generation* _next_gen; //对老年代的引用,初始化时为null,第一次GC时会赋值
  • uint        _tenuring_threshold; //将对象拷贝到老年代的分代年龄阈值,大于该值拷贝到老年代,否则拷贝到to区,该值在初始化时赋值成参数MaxTenuringThreshold,默认是15;每次GC结束后都会通过ageTable调整。
  • ageTable    _age_table; //记录不同分代年龄的对象的总大小
  • size_t      _pretenure_size_threshold_words; //表示年轻代中允许分配的对象的最大字宽数,默认是0,即无限制
  • bool   _promotion_failed; //记录是否出现promotion失败的oop
  • PromotionFailedInfo _promotion_failed_info; //记录promotion失败的对象信息
  • Stack<oop, mtGC>     _objs_with_preserved_marks; //记录promotion失败需要被保留的oop,如果对象头中包含锁,分代年龄等非初始化状态的信息,则需要单独保留,否则无法恢复
  • Stack<markOop, mtGC> _preserved_marks_of_objs; //记录promotion失败需要被保留的对象头
  • ExtendedOopClosure *_promo_failure_scan_stack_closure; //用来遍历_promo_failure_scan_stack中的oop所引用的其他对象
  • Stack<oop, mtGC> _promo_failure_scan_stack; //保存promotion失败的oop
  • bool _promo_failure_drain_in_progress; //是否应该处理_promo_failure_scan_stack中保存的oop
  • size_t               _max_eden_size;  //当年轻代达到最大内存时对应的eden区的内存,即eden区的最大内存
  • size_t               _max_survivor_size;//当年轻代达到最大内存时对应的survivor区的内存,即survivor区的最大内存
  • bool _should_allocate_from_space; // 是否从to区中分配对象
  • EdenSpace*       _eden_space; //三个内存区
  • ContiguousSpace* _from_space;
  • ContiguousSpace* _to_space; //注意to区正常情况下都是空的,只在垃圾回收的时候才使用
  • STWGCTimer* _gc_timer; //计时器

重点关注以下方法的实现。 

1、构造函数 / ref_processor_init

      构造函数负责初始化年轻代相关属性及三个内存区,ref_processor_init负责初始化父类属性ref_processor,两者的实现如下:

DefNewGeneration::DefNewGeneration(ReservedSpace rs,
                                   size_t initial_size,
                                   int level,
                                   const char* policy)
  : Generation(rs, initial_size, level),
    _promo_failure_drain_in_progress(false),
    _should_allocate_from_space(false)
{
  MemRegion cmr((HeapWord*)_virtual_space.low(),
                (HeapWord*)_virtual_space.high());
  //重置bs对应的内存区域
  Universe::heap()->barrier_set()->resize_covered_region(cmr);
  //has_soft_ended_eden方法的返回值取决于属性CMSIncrementalMode,默认为false
  //初始化三个内存区域
  if (GenCollectedHeap::heap()->collector_policy()->has_soft_ended_eden()) {
    _eden_space = new ConcEdenSpace(this);
  } else {
    _eden_space = new EdenSpace(this);
  }
  _from_space = new ContiguousSpace();
  _to_space   = new ContiguousSpace();

  if (_eden_space == NULL || _from_space == NULL || _to_space == NULL)
    vm_exit_during_initialization("Could not allocate a new gen space");

  //计算survivor区和eden区的最大空间,即年轻代最大内存时survivor区和eden区的内存空间
  uintx alignment = GenCollectedHeap::heap()->collector_policy()->space_alignment();
  uintx size = _virtual_space.reserved_size();
  _max_survivor_size = compute_survivor_size(size, alignment);
  _max_eden_size = size - (2*_max_survivor_size);

  //初始化性能统计的计数器
  _gen_counters = new GenerationCounters("new", 0, 3, &_virtual_space);
  _gc_counters = new CollectorCounters(policy, 0);

  _eden_counters = new CSpaceCounters("eden", 0, _max_eden_size, _eden_space,
                                      _gen_counters);
  _from_counters = new CSpaceCounters("s0", 1, _max_survivor_size, _from_space,
                                      _gen_counters);
  _to_counters = new CSpaceCounters("s1", 2, _max_survivor_size, _to_space,
                                    _gen_counters);
  
  //计算三个内存区的大小和边界,并初始化
  compute_space_boundaries(0, SpaceDecorator::Clear, SpaceDecorator::Mangle);
  //初始化计数器
  update_counters();
  _next_gen = NULL;
  //MaxTenuringThreshold表示属性tenuringThreshold的最大值,默认是15
  _tenuring_threshold = MaxTenuringThreshold;
  //PretenureSizeThreshold表示在DefNew代中分配的对象的最大字节数,默认是0,即无限制,这里是将其转换成字宽数
  _pretenure_size_threshold_words = PretenureSizeThreshold >> LogHeapWordSize;
  //初始化计时器
  _gc_timer = new (ResourceObj::C_HEAP, mtGC) STWGCTimer();
}

Generation::Generation(ReservedSpace rs, size_t initial_size, int level) :
  _level(level),
  _ref_processor(NULL) {
  //初始化ReservedSpace,并申请initial_size的内存
  if (!_virtual_space.initialize(rs, initial_size)) {
    vm_exit_during_initialization("Could not reserve enough space for "
                    "object heap");
  }
  if (ZapUnusedHeapArea) {
    //新申请的内存区域做Mangle填充处理
    MemRegion mangle_region((HeapWord*)_virtual_space.low(),
      (HeapWord*)_virtual_space.high());
    SpaceMangler::mangle_region(mangle_region);
  }
  _reserved = MemRegion((HeapWord*)_virtual_space.low_boundary(),
          (HeapWord*)_virtual_space.high_boundary());
}

//根据SurvivorRatio计算survivor的最大内存,该属性表示年轻代与survivor区内存的比值,默认是8,即默认配置下
//survivor区约占年轻代内存的10分之一
size_t compute_survivor_size(size_t gen_size, size_t alignment) const {
    size_t n = gen_size / (SurvivorRatio + 2);
    //向下做内存取整
    return n > alignment ? align_size_down(n, alignment) : alignment;
  }

void DefNewGeneration::compute_space_boundaries(uintx minimum_eden_size,
                                                bool clear_space,
                                                bool mangle_space) {
  uintx alignment =
    GenCollectedHeap::heap()->collector_policy()->space_alignment();

  assert(clear_space || (to()->is_empty() && from()->is_empty()),
    "Initialization of the survivor spaces assumes these are empty");

  //根据年轻代的当前大小计算survivor与eden区的大小
  uintx size = _virtual_space.committed_size();
  uintx survivor_size = compute_survivor_size(size, alignment);
  uintx eden_size = size - (2*survivor_size);
  assert(eden_size > 0 && survivor_size <= eden_size, "just checking");

  if (eden_size < minimum_eden_size) {
    //minimum_eden_size的值初始化时是0,在GC结束后且eden区不为空时则不为0
    //基于minimum_eden_size重新计算survivor与eden区的大小
    minimum_eden_size = align_size_up(minimum_eden_size, alignment);
    uintx maximum_survivor_size = (size - minimum_eden_size) / 2;
    uintx unaligned_survivor_size =
      align_size_down(maximum_survivor_size, alignment);
    survivor_size = MAX2(unaligned_survivor_size, alignment);
    eden_size = size - (2*survivor_size);
    assert(eden_size > 0 && survivor_size <= eden_size, "just checking");
    assert(eden_size >= minimum_eden_size, "just checking");
  }
  
  //计算三个内存区的边界
  char *eden_start = _virtual_space.low();
  char *from_start = eden_start + eden_size;
  char *to_start   = from_start + survivor_size;
  char *to_end     = to_start   + survivor_size;

  assert(to_end == _virtual_space.high(), "just checking");
  assert(Space::is_aligned((HeapWord*)eden_start), "checking alignment");
  assert(Space::is_aligned((HeapWord*)from_start), "checking alignment");
  assert(Space::is_aligned((HeapWord*)to_start),   "checking alignment");

  MemRegion edenMR((HeapWord*)eden_start, (HeapWord*)from_start);
  MemRegion fromMR((HeapWord*)from_start, (HeapWord*)to_start);
  MemRegion toMR  ((HeapWord*)to_start, (HeapWord*)to_end);

  //minimum_eden_size大于0表示当前eden区有部分空间被使用了
  bool live_in_eden = minimum_eden_size > 0;

  if (!clear_space) {
    if (ZapUnusedHeapArea) {
      //校验三个区是否经过mangle填充处理
      HeapWord* limit = (HeapWord*) _virtual_space.high();
      eden()->check_mangled_unused_area(limit);
      from()->check_mangled_unused_area(limit);
        to()->check_mangled_unused_area(limit);
    }
  }

  //初始化三个区
  eden()->initialize(edenMR,
                     clear_space && !live_in_eden,
                     SpaceDecorator::Mangle);
  if (ZapUnusedHeapArea && clear_space && live_in_eden && mangle_space) {
    eden()->mangle_unused_area();
  }
  from()->initialize(fromMR, clear_space, mangle_space);
  to()->initialize(toMR, clear_space, mangle_space);

  //from区作为eden区的下一个compaction_space
  eden()->set_next_compaction_space(from());
  //to区在开始compaction前正常都是空的,所以这里不考虑
  from()->set_next_compaction_space(NULL);
}

void DefNewGeneration::update_counters() {
  if (UsePerfData) {
    _eden_counters->update_all();
    _from_counters->update_all();
    _to_counters->update_all();
    _gen_counters->update_all();
  }
}

void DefNewGeneration::ref_processor_init() {
  Generation::ref_processor_init();
}

void Generation::ref_processor_init() {
  assert(_ref_processor == NULL, "a reference processor already exists");
  assert(!_reserved.is_empty(), "empty generation?");
  //初始化ReferenceProcessor
  _ref_processor = new ReferenceProcessor(_reserved);    // a vanilla reference processor
  if (_ref_processor == NULL) {
    vm_exit_during_initialization("Could not allocate ReferenceProcessor object");
  }
}

  两者的调用链如下:

即先初始化DefNewGeneration,再初始化其父类属性ref_processor

2、supports_tlab_allocation / tlab_capacity / tlab_used / unsafe_max_tlab_alloc

     这四个方法都是分配TLAB时使用的,其调用方主要是GenCollectedHeap,其实现如下:

bool supports_tlab_allocation() const { return true; }

size_t DefNewGeneration::tlab_capacity() const {
  return eden()->capacity();
}

size_t DefNewGeneration::tlab_used() const {
  return eden()->used();
}

size_t DefNewGeneration::unsafe_max_tlab_alloc() const {
  return unsafe_max_alloc_nogc();
}

size_t DefNewGeneration::unsafe_max_alloc_nogc() const {
  return eden()->free();
}

在开启TLAB时,基本所有的小对象都是在TLAB中分配的,不会直接在eden区中分配,所以eden区的capacity和used就是该年轻代用于分配TLAB的capacity和used。

3、object_iterate / space_iterate

      这两方法用来遍历年轻代中已分配的对象和所有的Space实例,其实现如下:

void DefNewGeneration::object_iterate(ObjectClosure* blk) {
  eden()->object_iterate(blk);
  from()->object_iterate(blk);
}

void DefNewGeneration::space_iterate(SpaceClosure* blk,
                                     bool usedOnly) {
  blk->do_space(eden());
  blk->do_space(from());
  blk->do_space(to());
}

4、should_allocate /allocate / par_allocate /  expand_and_allocate

      should_allocate方法判断当前DefNewGeneration是否支持指定大小的内存块的内存分配,后面三个都是用于分配指定大小的内存,其中expand_and_allocate的底层实现就是allocate并没有做扩展动作,其实现如下:

 // Allocation support
  virtual bool should_allocate(size_t word_size, bool is_tlab) {
    assert(UseTLAB || !is_tlab, "Should not allocate tlab");

    size_t overflow_limit    = (size_t)1 << (BitsPerSize_t - LogHeapWordSize);
    
    //校验word_size大于0,不超过overflow_limit,不超过_pretenure_size_threshold_words
    const bool non_zero      = word_size > 0;
    const bool overflows     = word_size >= overflow_limit;
    const bool check_too_big = _pretenure_size_threshold_words > 0;
    const bool not_too_big   = word_size < _pretenure_size_threshold_words;
    const bool size_ok       = is_tlab || !check_too_big || not_too_big;

    bool result = !overflows &&
                  non_zero   &&
                  size_ok;

    return result;
  }

const int BitsPerSize_t      = size_tSize * BitsPerByte;
//size_t在64位下,是long类型,8个字节
const int size_tSize         = sizeof(size_t);

HeapWord* DefNewGeneration::allocate(size_t word_size,
                                     bool is_tlab) {
  //正常情况下只有慢速分配对象时才会进入此方法,此时在GenCollectHeap层已经获取了锁                                   
  //par_allocate不要求调用方获取全局锁,底层使用cmpxchg原子指令,更快
  HeapWord* result = eden()->par_allocate(word_size);
  if (result != NULL) {
    //如果分配成功
    //CMSEdenChunksRecordAlways表示是否记录eden区分配的内存块,默认为true
    if (CMSEdenChunksRecordAlways && _next_gen != NULL) {
      _next_gen->sample_eden_chunk();
    }
    return result;
  }
  do {
    HeapWord* old_limit = eden()->soft_end();
    if (old_limit < eden()->end()) {
      //通知老年代,年轻代已经达到了分配限制soft_end,老年代会返回一个新的限制
      //非iCMS模式下,该方法就是返回NULL,就end和soft_end一直
      HeapWord* new_limit =
        next_gen()->allocation_limit_reached(eden(), eden()->top(), word_size);
      if (new_limit != NULL) {
        //原子的修改eden区的soft_end属性
        Atomic::cmpxchg_ptr(new_limit, eden()->soft_end_addr(), old_limit);
      } else {
        assert(eden()->soft_end() == eden()->end(),
               "invalid state after allocation_limit_reached returned null");
      }
    } else {
      //soft_end跟end一致了,必须扩容才能继续分配,终止循环
      assert(old_limit == eden()->end(), "sanity check");
      break;
    }
    //再次尝试分配,直到分配成功或者soft_end跟end一致
    result = eden()->par_allocate(word_size);
  } while (result == NULL);

  if (result == NULL) {
    result = allocate_from_space(word_size);
  } else if (CMSEdenChunksRecordAlways && _next_gen != NULL) {
    //while循环重试分配成功
    _next_gen->sample_eden_chunk();
  }
  return result;
}

//根据level从GenCollectedHeap中获取下一个Generation,并不是直接返回_next_gen属性
Generation* Generation::next_gen() const {
  GenCollectedHeap* gch = GenCollectedHeap::heap();
  int next = level() + 1;
  if (next < gch->_n_gens) {
    return gch->_gens[next];
  } else {
    return NULL;
  }
}

//尝试从from区分配对象
HeapWord* DefNewGeneration::allocate_from_space(size_t size) {
  HeapWord* result = NULL;
  if (Verbose && PrintGCDetails) {
    gclog_or_tty->print("DefNewGeneration::allocate_from_space(%u):"
                        "  will_fail: %s"
                        "  heap_lock: %s"
                        "  free: " SIZE_FORMAT,
                        size,
                        GenCollectedHeap::heap()->incremental_collection_will_fail(false /* don't consult_young */) ?
                          "true" : "false",
                        Heap_lock->is_locked() ? "locked" : "unlocked",
                        from()->free());
  }
  if (should_allocate_from_space() || GC_locker::is_active_and_needs_gc()) {
    if (Heap_lock->owned_by_self() ||
        (SafepointSynchronize::is_at_safepoint() &&
         Thread::current()->is_VM_thread())) {
      //只有在上述条件成立时才允许从from区中分配
      result = from()->allocate(size);
    } else if (PrintGC && Verbose) {
      gclog_or_tty->print_cr("  Heap_lock is not owned by self");
    }
  } else if (PrintGC && Verbose) {
    gclog_or_tty->print_cr("  should_allocate_from_space: NOT");
  }
  if (PrintGC && Verbose) {
    gclog_or_tty->print_cr("  returns %s", result == NULL ? "NULL" : "object");
  }
  return result;
}

bool should_allocate_from_space() const {
    return _should_allocate_from_space;
  }

HeapWord* DefNewGeneration::par_allocate(size_t word_size,
                                         bool is_tlab) {
  HeapWord* res = eden()->par_allocate(word_size);
  if (CMSEdenChunksRecordAlways && _next_gen != NULL) {
    _next_gen->sample_eden_chunk();
  }
  return res;
}

HeapWord* DefNewGeneration::expand_and_allocate(size_t size,
                                                bool   is_tlab,
                                                bool   parallel) {
  // We don't attempt to expand the young generation (but perhaps we should.)
  return allocate(size, is_tlab);
}

其调用链如下:

 5、oop_since_save_marks_iterate

      该方法一组通过宏定义的多个方法,用于遍历年轻代三个Space的saved_mark_word属性到top属性之间的对象所引用的对象,包含如下方法:

其实现如下:

#define DefNew_SINCE_SAVE_MARKS_DEFN(OopClosureType, nv_suffix) \
                                                                \
void DefNewGeneration::                                         \
oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl) {   \
  cl->set_generation(this);                                     \
  eden()->oop_since_save_marks_iterate##nv_suffix(cl);          \
  to()->oop_since_save_marks_iterate##nv_suffix(cl);            \
  from()->oop_since_save_marks_iterate##nv_suffix(cl);          \
  cl->reset_generation();                                       \
  save_marks();                                                 \
}

ALL_SINCE_SAVE_MARKS_CLOSURES(DefNew_SINCE_SAVE_MARKS_DEFN)

#undef DefNew_SINCE_SAVE_MARKS_DEFN

void DefNewGeneration::save_marks() {
  eden()->set_saved_mark();
  to()->set_saved_mark();
  from()->set_saved_mark();
}

void set_saved_mark()            { _saved_mark_word = top();    }

 6、contribute_scratch / reset_scratch

       contribute_scratch方法用于老年代从年轻代的to区申请一块指定大小的内存,reset_scratch用于重置to区,如果ZapUnusedHeapArea为true,则将整个to区重新填充,其实现如下:

void DefNewGeneration::contribute_scratch(ScratchBlock*& list, Generation* requestor,
                                         size_t max_alloc_words) {
  //必须是老年代请求,level大于年轻代的level                                       
  if (requestor == this || _promotion_failed) return;
  assert(requestor->level() > level(), "DefNewGeneration must be youngest");

  ContiguousSpace* to_space = to();
  assert(to_space->end() >= to_space->top(), "pointers out of order");
  size_t free_words = pointer_delta(to_space->end(), to_space->top());
  //注意此处并未校验free_words是否大于max_alloc_words,也并未在分配结束后修改top属性
  if (free_words >= MinFreeScratchWords) {
    //构造一个ScratchBlock实例
    ScratchBlock* sb = (ScratchBlock*)to_space->top();
    sb->num_words = free_words;
    //将list插入到sb的后面
    sb->next = list;
    list = sb;
  }
}

void DefNewGeneration::reset_scratch() {
  //因为top属性未修改,所以是整个to区都被mangle了
  if (ZapUnusedHeapArea) {
    to()->mangle_unused_area_complete();
  }
}

ScratchBlock的定义如下:

其调用链如下:

发布了117 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_31865983/article/details/104076352