目录
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 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;
}
其调用链如下: