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的发生时间
- jMemRegion _prev_used_region; //在GC过程中的某个特殊时点使用的,用于记录某个值
- jMemRegion _reserved; //为当前Generation保留的一段连续的内存地址空间,注意不能跟其他的Generation的地址空间有交叉
- jVirtualSpace _virtual_space; //同上
- jint _level; //当前Generation在类继承关系中的级别
- jReferenceProcessor* _ref_processor; //用于处理Reference实例的处理器
- jCollectorCounters* _gc_counters; //用于GC性能跟踪
- jGCStats* _gc_stats; //收集GC的统计数据
- jStatRecord _stat_record; //用于GC性能跟踪
Generation定义了一个枚举Name来描述各子类,其定义如下:
image.pngMarkSweepCompact就是上面类继承关系中的TenuredGeneration,可以通过kind方法获取当前Generation实例的类型,其默认实现如下:
image.png重点关注以下方法的实现。
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) {}
};
两方法的调用链如下:
image.pngimage.png
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; }
};
image.png
image.png
image.png
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) {}
};
其调用链如下:
image.pngimage.png image.png
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();
}
}
其调用链如下:
image.png image.png image.pngDefNewGeneration
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");
}
}
两者的调用链如下:
image.png image.png即先初始化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);
}
其调用链如下:
image.png image.png image.png
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的定义如下:
image.png
其调用链如下:
image.png
image.png
网友评论