目录
5、IsAliveClosure / ScanWeakRefClosure / FastKeepAliveClosure
6、FastScanClosure / KlassScanClosure / CLDToKlassAndOopClosure / FastEvacuateFollowersClosure
本篇博客继续上一篇《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->set_incremental_collection_failed(); // Slight lie: a full gc left us in that state
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,to区只有通过allocate_from_space方法分配对象才会非空,正常都是空的
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;
}
其调用链如下:
3、copy_to_survivor_space
copy_to_survivor_space会将对象拷贝到to区或者老年代,如果对象的分代年龄大于tenuring_threshold或者从to区申请内存失败则拷贝到老年代,否则拷贝到to区;如果拷贝到老年代失败,则_promotion_failed置为true,并将该对象保存到_promo_failure_scan_stack栈中。其实现如下:
oop DefNewGeneration::copy_to_survivor_space(oop old) {
assert(is_in_reserved(old) && !old->is_forwarded(),
"shouldn't be scavenging this oop");
size_t s = old->size();
oop obj = NULL;
// Try allocating obj in to-space (unless too old)
if (old->age() < tenuring_threshold()) {
//如果对象的年龄低于tenuring_threshold,则该在to区申请一块同样大小的内存
obj = (oop) to()->allocate_aligned(s);
}
// Otherwise try allocating obj tenured
if (obj == NULL) {
//如果如果对象的年龄大于tenuring_threshold或者to区申请内存失败
//则尝试将该对象复制到老年代
obj = _next_gen->promote(old, s);
if (obj == NULL) {
//复制失败
handle_promotion_failure(old);
return old;
}
} else {
//to区中申请内存成功
const intx interval = PrefetchCopyIntervalInBytes;
Prefetch::write(obj, interval);
//对象复制
Copy::aligned_disjoint_words((HeapWord*)old, (HeapWord*)obj, s);
//增加年龄,并修改age_table,增加对应年龄的总对象大小
obj->incr_age();
age_table()->add(obj, s);
}
//将对象头指针指向新地址
old->forward_to(obj);
return obj;
}
//从请求头中获取对象的年龄
inline uint oopDesc::age() const {
assert(!is_forwarded(), "Attempt to read age from forwarded mark");
if (has_displaced_mark()) {
return displaced_mark()->age();
} else {
return mark()->age();
}
}
uint tenuring_threshold() { return _tenuring_threshold; }
void DefNewGeneration::handle_promotion_failure(oop old) {
if (PrintPromotionFailure && !_promotion_failed) {
gclog_or_tty->print(" (promotion failure size = " SIZE_FORMAT ") ",
old->size());
}
_promotion_failed = true;
_promotion_failed_info.register_copy_failure(old->size());
preserve_mark_if_necessary(old, old->mark());
//将old的对象头指针指向它自己
old->forward_to(old);
//保存promotion失败的对象
_promo_failure_scan_stack.push(old);
//_promo_failure_drain_in_progress初始化为false
if (!_promo_failure_drain_in_progress) {
// prevent recursion in copy_to_survivor_space()
_promo_failure_drain_in_progress = true;
drain_promo_failure_scan_stack();
_promo_failure_drain_in_progress = false;
}
}
void DefNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) {
//是否要保留promotion失败的对象,对象头中包含锁,分代年龄等非初始状态的信息时需要单独保留对象头,否则无法恢复成原来的状态
if (m->must_be_preserved_for_promotion_failure(obj)) {
preserve_mark(obj, m);
}
}
//保留指定的对象和对象头
void DefNewGeneration::preserve_mark(oop obj, markOop m) {
assert(_promotion_failed && m->must_be_preserved_for_promotion_failure(obj),
"Oversaving!");
_objs_with_preserved_marks.push(obj);
_preserved_marks_of_objs.push(m);
}
//用于移除并处理_promo_failure_scan_stack中保存的对象
void DefNewGeneration::drain_promo_failure_scan_stack() {
while (!_promo_failure_scan_stack.is_empty()) {
oop obj = _promo_failure_scan_stack.pop();
obj->oop_iterate(_promo_failure_scan_stack_closure);
}
}
其调用链如下:
4、 ageTable
ageTable的定义在hotspot\src\share\vm\gc_implementation\shared\ageTable.hpp中,用来记录不同分代年龄的对象的大小,然后据此动态调整tenuring_threshold,重要属性只有一个,如下:
sizes就是保存不同分代年龄的对象的大小的数组。重点关注以下方法的实现,clear方法用于将sizes数组中各元素的值置为0,add方法用于增加某个分代年龄下的对象大小,compute_tenuring_threshold方法用于计算新的tenuring_threshold,保证to区中已使用空间占总空间的比例满足TargetSurvivorRatio的要求,如下:
ageTable::ageTable(bool global) {
clear();
if (UsePerfData && global) {
ResourceMark rm;
EXCEPTION_MARK;
const char* agetable_ns = "generation.0.agetable";
const char* bytes_ns = PerfDataManager::name_space(agetable_ns, "bytes");
//初始化用于收集性能的PerfVariable
for(int age = 0; age < table_size; age ++) {
char age_name[10];
jio_snprintf(age_name, sizeof(age_name), "%2.2d", age);
const char* cname = PerfDataManager::counter_name(bytes_ns, age_name);
_perf_sizes[age] = PerfDataManager::create_variable(SUN_GC, cname,
PerfData::U_Bytes,
CHECK);
}
const char* cname = PerfDataManager::counter_name(agetable_ns, "size");
PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_None,
table_size, CHECK);
}
}
void ageTable::clear() {
//将所有的数组元素的值重置为0
for (size_t* p = sizes; p < sizes + table_size; ++p) {
*p = 0;
}
}
void add(oop p, size_t oop_size) {
add(p->age(), oop_size);
}
void add(uint age, size_t oop_size) {
assert(age > 0 && age < table_size, "invalid age of object");
sizes[age] += oop_size;
}
uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
//TargetSurvivorRatio表示GC后Survivor区已使用内存占总内存的比例,默认是50
//计算期望的survivor区的大小
size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
size_t total = 0;
uint age = 1;
assert(sizes[0] == 0, "no objects with age zero should be recorded");
//从低到高依次遍历ageTable,将给分代年龄对应的对象大小加起来,一旦超过desired_survivor_size,则该age就是目标age
//低于该age的对象就会被拷贝到to区,从而保证Survivor区的内存在GC结束后满足TargetSurvivorRatio限制
while (age < table_size) {
total += sizes[age];
// check if including objects of age 'age' made us pass the desired
// size, if so 'age' is the new threshold
if (total > desired_survivor_size) break;
age++;
}
uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
if (PrintTenuringDistribution || UsePerfData) {
//打印日志,更新PerfData和相关计数器
if (PrintTenuringDistribution) {
gclog_or_tty->cr();
gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold %u (max %u)",
desired_survivor_size*oopSize, result, (int) MaxTenuringThreshold);
}
total = 0;
age = 1;
while (age < table_size) {
total += sizes[age];
if (sizes[age] > 0) {
if (PrintTenuringDistribution) {
gclog_or_tty->print_cr("- age %3u: " SIZE_FORMAT_W(10) " bytes, " SIZE_FORMAT_W(10) " total",
age, sizes[age]*oopSize, total*oopSize);
}
}
if (UsePerfData) {
_perf_sizes[age]->set_value(sizes[age]*oopSize);
}
age++;
}
if (UsePerfData) {
SharedHeap* sh = SharedHeap::heap();
CollectorPolicy* policy = sh->collector_policy();
GCPolicyCounters* gc_counters = policy->counters();
gc_counters->tenuring_threshold()->set_value(result);
gc_counters->desired_survivor_size()->set_value(
desired_survivor_size*oopSize);
}
}
return result;
}
5、IsAliveClosure / ScanWeakRefClosure / FastKeepAliveClosure
IsAliveClosure用来判断某个oop是否是存活的;ScanWeakRefClosure用于扫描弱引用的;FastKeepAliveClosure继承自KeepAliveClosure,只适用于DefNewGeneration,用于将某个oop标记成存活状态,具体来说就是将该对象拷贝到to区或者老年代,然后更新对象的对象头指针和BS对应的卡表项,从而让is_forwarded方法返回true;上述三个类,除ScanWeakRefClosure定义在hotspot\src\share\vm\memory\genOopClosures.hpp中,另外两个都在同目录的defNewGeneration.hpp中,其实现如下:
//IsAliveClosure只适用于年轻代
DefNewGeneration::IsAliveClosure::IsAliveClosure(Generation* g) : _g(g) {
assert(g->level() == 0, "Optimized for youngest gen.");
}
bool DefNewGeneration::IsAliveClosure::do_object_b(oop p) {
//如果p不在年轻代或者p即将被复制则认为p是存活的
return (HeapWord*)p >= _g->reserved().end() || p->is_forwarded();
}
ScanWeakRefClosure::ScanWeakRefClosure(DefNewGeneration* g) :
_g(g)
{
assert(_g->level() == 0, "Optimized for youngest generation");
_boundary = _g->reserved().end();
}
void ScanWeakRefClosure::do_oop(oop* p) { ScanWeakRefClosure::do_oop_work(p); }
void ScanWeakRefClosure::do_oop(narrowOop* p) { ScanWeakRefClosure::do_oop_work(p); }
inline void ScanWeakRefClosure::do_oop_nv(oop* p) { ScanWeakRefClosure::do_oop_work(p); }
inline void ScanWeakRefClosure::do_oop_nv(narrowOop* p) { ScanWeakRefClosure::do_oop_work(p); }
template <class T> inline void ScanWeakRefClosure::do_oop_work(T* p) {
//校验oop非空
assert(!oopDesc::is_null(*p), "null weak reference?");
//获取oop
oop obj = oopDesc::load_decode_heap_oop_not_null(p);
//校验obj在年轻代中且不在to区中
if ((HeapWord*)obj < _boundary && !_g->to()->is_in_reserved(obj)) {
//获取obj的拷贝地址,如果该对象因为Space压缩已经有拷贝地址则使用该地址,否则将该对象拷贝到to区或者老年代
//copy_to_survivor_space方法会完成拷贝并返回拷贝到to区或者老年代的新地址,如果拷贝失败返回NULL
oop new_obj = obj->is_forwarded() ? obj->forwardee()
: _g->copy_to_survivor_space(obj);
//将p指向新地址
oopDesc::encode_store_heap_oop_not_null(p, new_obj);
}
}
DefNewGeneration::KeepAliveClosure::
KeepAliveClosure(ScanWeakRefClosure* cl) : _cl(cl) {
GenRemSet* rs = GenCollectedHeap::heap()->rem_set();
assert(rs->rs_kind() == GenRemSet::CardTable, "Wrong rem set kind.");
_rs = (CardTableRS*)rs;
}
void DefNewGeneration::KeepAliveClosure::do_oop(oop* p) { DefNewGeneration::KeepAliveClosure::do_oop_work(p); }
void DefNewGeneration::KeepAliveClosure::do_oop(narrowOop* p) { DefNewGeneration::KeepAliveClosure::do_oop_work(p); }
template <class T>
inline void DefNewGeneration::KeepAliveClosure::do_oop_work(T* p) {
_cl->do_oop_nv(p);
if (Universe::heap()->is_in_reserved(p)) {
oop obj = oopDesc::load_decode_heap_oop_not_null(p);
//将对应的卡表项设置为youngergen_card,而非脏的
_rs->inline_write_ref_field_gc(p, obj);
}
//FastKeepAliveClosure只适用于DefNewGeneration
DefNewGeneration::FastKeepAliveClosure::
FastKeepAliveClosure(DefNewGeneration* g, ScanWeakRefClosure* cl) :
DefNewGeneration::KeepAliveClosure(cl) {
_boundary = g->reserved().end();
}
void DefNewGeneration::FastKeepAliveClosure::do_oop(oop* p) { DefNewGeneration::FastKeepAliveClosure::do_oop_work(p); }
void DefNewGeneration::FastKeepAliveClosure::do_oop(narrowOop* p) { DefNewGeneration::FastKeepAliveClosure::do_oop_work(p); }
template <class T>
inline void DefNewGeneration::FastKeepAliveClosure::do_oop_work(T* p) {
_cl->do_oop_nv(p);
oop obj = oopDesc::load_decode_heap_oop_not_null(p);
//同KeepAliveClosure的实现,多了一个地址范围的判断
if (((HeapWord*)obj < _boundary) && Universe::heap()->is_in_reserved(p)) {
_rs->inline_write_ref_field_gc(p, obj);
}
}
6、FastScanClosure / KlassScanClosure / CLDToKlassAndOopClosure / FastEvacuateFollowersClosure
FastScanClosure用于遍历存活对象的引用类型属性,修改该属性的值使其指向对象的新地址,即对象头中的forward指针,最后根据参数修改bs;如果已经有Space压缩生成的forword指针则直接使用,否则根据对象的分代年龄将对象拷贝到to区或者老年代,并将拷贝的目标地址写入对象头中。KlassScanClosure与FastScanClosure配合使用,用来遍历Klass对应的类Class实例,遍历逻辑就是FastScanClosure。CLDToKlassAndOopClosure与FastScanClosure,KlassScanClosure配合使用,用来遍历一个ClassLoader实例加载的所有类的Class实例及其关联的依赖,常量池引用等。FastEvacuateFollowersClosure比较特殊,用来遍历所有Space的_saved_mark_word属性到top属性之间的对象的所有引用类型属性。
FastScanClosure::FastScanClosure(DefNewGeneration* g, bool gc_barrier) :
OopsInKlassOrGenClosure(g), _g(g), _gc_barrier(gc_barrier)
{
assert(_g->level() == 0, "Optimized for youngest generation");
_boundary = _g->reserved().end();
}
void FastScanClosure::do_oop(oop* p) { FastScanClosure::do_oop_work(p); }
void FastScanClosure::do_oop(narrowOop* p) { FastScanClosure::do_oop_work(p); }
inline void FastScanClosure::do_oop_nv(oop* p) { FastScanClosure::do_oop_work(p); }
inline void FastScanClosure::do_oop_nv(narrowOop* p) { FastScanClosure::do_oop_work(p); }
template <class T> inline void FastScanClosure::do_oop_work(T* p) {
T heap_oop = oopDesc::load_heap_oop(p);
// Should we copy the obj?
if (!oopDesc::is_null(heap_oop)) {
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
if ((HeapWord*)obj < _boundary) {
assert(!_g->to()->is_in_reserved(obj), "Scanning field twice?");
oop new_obj = obj->is_forwarded() ? obj->forwardee()
: _g->copy_to_survivor_space(obj);
oopDesc::encode_store_heap_oop_not_null(p, new_obj);
if (is_scanning_a_klass()) {
do_klass_barrier();
} else if (_gc_barrier) {
// Now call parent closure
do_barrier(p);
}
}
}
}
OopsInKlassOrGenClosure(Generation* g) : OopsInGenClosure(g), _scanned_klass(NULL) {}
bool is_scanning_a_klass() { return _scanned_klass != NULL; }
inline void OopsInKlassOrGenClosure::do_klass_barrier() {
assert(_scanned_klass != NULL, "Must be");
_scanned_klass->record_modified_oops();
}
template <class T> inline void OopsInGenClosure::do_barrier(T* p) {
assert(generation()->is_in_reserved(p), "expected ref in generation");
//获取p指向的对象地址
T heap_oop = oopDesc::load_heap_oop(p);
assert(!oopDesc::is_null(heap_oop), "expected non-null oop");
//获取heap_oop的完整地址
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
//_gen_boundary是当前generation的起始地址,如果obj小于gen_boundary,说明obj是更年轻的分代中的
if ((HeapWord*)obj < _gen_boundary) {
//将对应的卡表项标记为youngergen_card
_rs->inline_write_ref_field_gc(p, obj);
}
}
KlassScanClosure::KlassScanClosure(OopsInKlassOrGenClosure* scavenge_closure,
KlassRemSet* klass_rem_set)
: _scavenge_closure(scavenge_closure),
_accumulate_modified_oops(klass_rem_set->accumulate_modified_oops()) {}
void KlassScanClosure::do_klass(Klass* klass) {
// If the klass has not been dirtied we know that there's
// no references into the young gen and we can skip it.
if (klass->has_modified_oops()) {
if (_accumulate_modified_oops) {
klass->accumulate_modified_oops();
}
// Clear this state since we're going to scavenge all the metadata.
klass->clear_modified_oops();
//通知_scavenge_closure准备扫描klass
_scavenge_closure->set_scanned_klass(klass);
klass->oops_do(_scavenge_closure);
_scavenge_closure->set_scanned_klass(NULL);
}
}
void Klass::oops_do(OopClosure* cl) {
cl->do_oop(&_java_mirror);
}
CLDToKlassAndOopClosure(KlassClosure* klass_closure,
OopClosure* oop_closure,
bool must_claim_cld) :
_oop_closure(oop_closure),
_klass_closure(klass_closure),
_must_claim_cld(must_claim_cld) {}
void CLDToKlassAndOopClosure::do_cld(ClassLoaderData* cld) {
cld->oops_do(_oop_closure, _klass_closure, _must_claim_cld);
}
void ClassLoaderData::oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) {
if (must_claim && !claim()) {
return;
}
f->do_oop(&_class_loader);
_dependencies.oops_do(f);
_handles.oops_do(f);
if (klass_closure != NULL) {
classes_do(klass_closure);
}
}
DefNewGeneration::FastEvacuateFollowersClosure::
FastEvacuateFollowersClosure(GenCollectedHeap* gch, int level,
DefNewGeneration* gen,
FastScanClosure* cur, FastScanClosure* older) :
_gch(gch), _level(level), _gen(gen),
_scan_cur_or_nonheap(cur), _scan_older(older)
{}
void DefNewGeneration::FastEvacuateFollowersClosure::do_void() {
do {
_gch->oop_since_save_marks_iterate(_level, _scan_cur_or_nonheap,
_scan_older);
} while (!_gch->no_allocs_since_save_marks(_level));
guarantee(_gen->promo_failure_scan_is_complete(), "Failed to finish scan");
}
7、collect
collect就是DefNewGeneration执行GC的核心入口方法了,其中引用遍历的逻辑都封装在GenCollectedHeap::gen_process_roots方法中了,本方法主要完成引用遍历前后的处理逻辑,这里重点关注年轻代三个区的使用。参考上一篇《Hotspot 垃圾回收之DefNewGeneration(一) 源码解析》中分析的allocate方法及其相关方法的实现可知,年轻代对象分配主要在eden区,只有在eden区和老年代都满了导致promote失败才可能在from区中分配内存,正常情况下to区是空的,GC引用遍历时会遍历eden区和from区的对象,这个过程中如果存活对象的分代年龄小于tenuring_threshold则会拷贝到to区中并增加分代年龄,大于该阈值的就拷贝到老年代中,遍历结束后如果没有promote失败则认为所有存活对象都已成功复制,会清空eden区和from区,然后交换from区和to区,即空的from区变成to区,包含有存活对象的to区变成from区,如此循环往复,to区会一直是空的;如果老年代空间不足,出现promote失败的情形,则eden区和from区存在尚未复制的存活对象,则不能清空此时的eden区和from区,这时需要将eden区和from区中对象的对象头恢复成初始状态,即去掉forward指针,然后交换from区和to区,并且将交换后的to区作为from区的next_compaction_space(正常是null),从而尽可能的利用剩余的年轻代内存空间,此时的to区因为是原来的包含存活对象的from区,所以不是空的。
void DefNewGeneration::collect(bool full,
bool clear_all_soft_refs,
size_t size,
bool is_tlab) {
assert(full || size > 0, "otherwise we don't want to collect");
GenCollectedHeap* gch = GenCollectedHeap::heap();
//记录GC的开始时间和原因
_gc_timer->register_gc_start();
DefNewTracer gc_tracer;
gc_tracer.report_gc_start(gch->gc_cause(), _gc_timer->gc_start());
_next_gen = gch->next_gen(this);
//判断老年代是否有足够的空间保存年轻代复制过去的对象
if (!collection_attempt_is_safe()) {
if (Verbose && PrintGCDetails) {
gclog_or_tty->print(" :: Collection attempt not safe :: ");
}
//老年代空间不足,终止年轻代的GC
gch->set_incremental_collection_failed(); // Slight lie: we did not even attempt one
return;
}
assert(to()->is_empty(), "Else not collection_attempt_is_safe");
//将_promotion_failed属性置为false,记录promote失败信息的PromotionFailedInfo重置成初始状态
init_assuming_no_promotion_failure();
GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL, gc_tracer.gc_id());
// Capture heap used before collection (for printing).
size_t gch_prev_used = gch->used();
//设置GC Tracer
gch->trace_heap_before_gc(&gc_tracer);
SpecializationStats::clear();
//初始化两个遍历器
IsAliveClosure is_alive(this);
ScanWeakRefClosure scan_weak_ref(this);
//重置ageTable
age_table()->clear();
//重置to区
to()->clear(SpaceDecorator::Mangle);
//重置cur_youngergen_card_val
gch->rem_set()->prepare_for_younger_refs_iterate(false);
assert(gch->no_allocs_since_save_marks(0),
"save marks have not been newly set.");
CollectorPolicy* cp = gch->collector_policy();
//FastScanClosure用来遍历oop*,即Java对象中的引用类型属性
FastScanClosure fsc_with_no_gc_barrier(this, false);
FastScanClosure fsc_with_gc_barrier(this, true);
//KlassScanClosure用来遍历某个类对应的Class实例
KlassScanClosure klass_scan_closure(&fsc_with_no_gc_barrier,
gch->rem_set()->klass_rem_set());
//CLDToKlassAndOopClosure用来遍历一个ClassLoader加载的所有类对应的Class实例和依赖等
CLDToKlassAndOopClosure cld_scan_closure(&klass_scan_closure,
&fsc_with_no_gc_barrier,
false);
set_promo_failure_scan_stack_closure(&fsc_with_no_gc_barrier);
//FastEvacuateFollowersClosure用来遍历从saved_mark属性到top之间的oop
FastEvacuateFollowersClosure evacuate_followers(gch, _level, this,
&fsc_with_no_gc_barrier,
&fsc_with_gc_barrier);
assert(gch->no_allocs_since_save_marks(0),
"save marks have not been newly set.");
//执行引用遍历
gch->gen_process_roots(_level,
true, // Process younger gens, if any,
// as strong roots.
true, // activate StrongRootsScope
GenCollectedHeap::SO_ScavengeCodeCache,
GenCollectedHeap::StrongAndWeakRoots,
&fsc_with_no_gc_barrier,
&fsc_with_gc_barrier,
&cld_scan_closure);
//执行遍历
evacuate_followers.do_void();
FastKeepAliveClosure keep_alive(this, &scan_weak_ref);
ReferenceProcessor* rp = ref_processor();
rp->setup_policy(clear_all_soft_refs);
//过滤所有找到的references实例
const ReferenceProcessorStats& stats =
rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers,
NULL, _gc_timer, gc_tracer.gc_id());
gc_tracer.report_gc_reference_stats(stats);
if (!_promotion_failed) {
//promote没有失败的
//重置eden区和from区
eden()->clear(SpaceDecorator::Mangle);
from()->clear(SpaceDecorator::Mangle);
if (ZapUnusedHeapArea) {
to()->mangle_unused_area();
}
//交换from区和to区
swap_spaces();
//交换后,原来的from区变成to区,必须是空的
assert(to()->is_empty(), "to space should be empty now");
//调整tenuring_threshold
adjust_desired_tenuring_threshold();
AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
//重置gc_overhead_limit_count
size_policy->reset_gc_overhead_limit_count();
if (PrintGC && !PrintGCDetails) {
gch->print_heap_change(gch_prev_used);
}
assert(!gch->incremental_collection_failed(), "Should be clear");
} else {
//如果存在promote失败的情形
assert(_promo_failure_scan_stack.is_empty(), "post condition");
//清空保存promo_failure的oop的栈
_promo_failure_scan_stack.clear(true); // Clear cached segments.
//移除from区和eden区包含的对象的froward指针
remove_forwarding_pointers();
if (PrintGCDetails) {
gclog_or_tty->print(" (promotion failed) ");
}
//交换from区和to区,注意此时eden区和from区因为promote失败所以不是空的,还有存活对象
swap_spaces(); // For uniformity wrt ParNewGeneration.
//将to区作为from区的next_compaction_space,正常为NULL
from()->set_next_compaction_space(to());
gch->set_incremental_collection_failed();
//通知老年代promote失败.
_next_gen->promotion_failure_occurred();
gc_tracer.report_promotion_failed(_promotion_failed_info);
}
//设置并行遍历时的边界
from()->set_concurrent_iteration_safe_limit(from()->top());
to()->set_concurrent_iteration_safe_limit(to()->top());
SpecializationStats::print();
//更新GC完成时间
jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;
update_time_of_last_gc(now);
gch->trace_heap_after_gc(&gc_tracer);
gc_tracer.report_tenuring_threshold(tenuring_threshold());
_gc_timer->register_gc_end();
//更新GC日志
gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions());
}
void DefNewGeneration::init_assuming_no_promotion_failure() {
_promotion_failed = false;
_promotion_failed_info.reset();
from()->set_next_compaction_space(NULL);
}
void set_promo_failure_scan_stack_closure(ExtendedOopClosure *scan_stack_closure) {
_promo_failure_scan_stack_closure = scan_stack_closure;
}
void DefNewGeneration::swap_spaces() {
//交换from区和to区对应的内存区域
ContiguousSpace* s = from();
_from_space = to();
_to_space = s;
//重置eden区的next_compaction_space
eden()->set_next_compaction_space(from());
//将原来的to区的next_compaction_space置为null
from()->set_next_compaction_space(NULL);
if (UsePerfData) {
CSpaceCounters* c = _from_counters;
_from_counters = _to_counters;
_to_counters = c;
}
}
void DefNewGeneration::adjust_desired_tenuring_threshold() {
//重置tenuring_threshold,注意此处传入的是to区的容量,因为对象是往to区拷贝的
_tenuring_threshold =
age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize);
}
void DefNewGeneration::remove_forwarding_pointers() {
RemoveForwardPointerClosure rspc;
//遍历eden区和from区中的对象,将对象头恢复成初始状态,即去掉原来对象头中包含的forward指针,即该对象拷贝的目标地址
eden()->object_iterate(&rspc);
from()->object_iterate(&rspc);
// Now restore saved marks, if any.
assert(_objs_with_preserved_marks.size() == _preserved_marks_of_objs.size(),
"should be the same");
//遍历_objs_with_preserved_marks,恢复其中保存的oop的对象头
while (!_objs_with_preserved_marks.is_empty()) {
oop obj = _objs_with_preserved_marks.pop();
markOop m = _preserved_marks_of_objs.pop();
obj->set_mark(m);
}
//清空两个栈
_objs_with_preserved_marks.clear(true);
_preserved_marks_of_objs.clear(true);
}
class RemoveForwardPointerClosure: public ObjectClosure {
public:
void do_object(oop obj) {
obj->init_mark();
}
};
virtual void update_time_of_last_gc(jlong now) {
_time_of_last_gc = now;
}