Repository navigation
g1 evacuation_Young
ceragon edited this page Dec 27, 2021
·
3 revisions
- 调用的方式为构造 VM_G1CollectForAllocation 类,且 gc_cause 一般为 _g1_inc_collection_pause
123
class VM_G1CollectForAllocation: public VM_CollectForAllocation {
public:
VM_G1CollectForAllocation(size_t word_size,
uint gc_count_before,
GCCause::Cause gc_cause,
bool should_initiate_conc_mark,
double target_pause_time_ms);
};- 反查使用 _g1_inc_collection_pause 的使用,得到如下代码
HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size) {
if (should_try_gc) {
bool succeeded;
result = do_collection_pause(word_size, gc_count_before, &succeeded,
GCCause::_g1_inc_collection_pause);
}
}- 而上面的 do_collection_pause 方法内容如下,由此可得 attempt_allocation_slow() 是造成 Young GC 的主要原因
HeapWord* G1CollectedHeap::do_collection_pause(size_t word_size,
uint gc_count_before,
bool* succeeded,
GCCause::Cause gc_cause) {
VM_G1CollectForAllocation op(word_size,
gc_count_before,
gc_cause,
false, /* should_initiate_conc_mark */
g1_policy()->max_pause_time_ms());
VMThread::execute(&op);
}- 该
inline HeapWord* G1CollectedHeap::attempt_allocation(size_t min_word_size,
size_t desired_word_size,
size_t* actual_word_size) {
// 普通分配的方法
HeapWord* result = _allocator->attempt_allocation(min_word_size, desired_word_size, actual_word_size);
if (result == NULL) {
*actual_word_size = desired_word_size;
// 没有分配成功的时候,会尝试慢分配
result = attempt_allocation_slow(desired_word_size);
}
}- 继续
HeapWord* G1CollectedHeap::allocate_new_tlab(size_t min_size,
size_t requested_size,
size_t* actual_size) {
return attempt_allocation(min_size, requested_size, actual_size);
}HeapWord* G1CollectedHeap::mem_allocate(size_t word_size, bool* gc_overhead_limit_was_exceeded) {
size_t dummy = 0;
return attempt_allocation(word_size, word_size, &dummy);
}HeapWord* MemAllocator::allocate_inside_tlab_slow(Allocation& allocation) const {
mem = _heap->allocate_new_tlab(min_tlab_size, new_tlab_size, &allocation._allocated_tlab_size);
}HeapWord* MemAllocator::allocate_outside_tlab(Allocation& allocation) const {
HeapWord* mem = _heap->mem_allocate(_word_size, &allocation._overhead_limit_exceeded);
}可以看到无论 inside 还是 outside 都是 TLAB 相关信息,详见 Thread Local Allocate Buffer
HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size) {
ResourceMark rm; // For retrieving the thread names in log messages.
HeapWord* result = NULL;
for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) {
bool should_try_gc;
uint gc_count_before;
{
MutexLockerEx x(Heap_lock);
result = _allocator->attempt_allocation_locked(word_size);
if (result != NULL) {
return result;
}
if (GCLocker::is_active_and_needs_gc() && g1_policy()->can_expand_young_list()) {
result = _allocator->attempt_allocation_force(word_size);
if (result != NULL) {
return result;
}
}
should_try_gc = !GCLocker::needs_gc();
gc_count_before = total_collections();
}
if (should_try_gc) {
bool succeeded;
result = do_collection_pause(word_size, gc_count_before, &succeeded,
GCCause::_g1_inc_collection_pause);
// 省略代码
}
// 省略代码
}
return NULL;
}- 方法内容如下
inline HeapWord* G1Allocator::attempt_allocation_locked(size_t word_size) {
HeapWord* result = mutator_alloc_region()->attempt_allocation_locked(word_size);
return result;
}- 代码
inline HeapWord* G1AllocRegion::attempt_allocation_locked(size_t word_size) {
return attempt_allocation_locked(word_size, word_size, &temp);
}- 继续
inline HeapWord* G1AllocRegion::attempt_allocation_locked(size_t min_word_size,
size_t desired_word_size,
size_t* actual_word_size) {
HeapWord* result = attempt_allocation(min_word_size, desired_word_size, actual_word_size);
if (result != NULL) {
return result;
}
retire(true /* fill_up */);
result = new_alloc_region_and_allocate(desired_word_size, false /* force */);
if (result != NULL) {
*actual_word_size = desired_word_size;
return result;
}
return NULL;
}- 继续
inline HeapWord* G1AllocRegion::attempt_allocation(size_t min_word_size,
size_t desired_word_size,
size_t* actual_word_size) {
HeapRegion* alloc_region = _alloc_region;
HeapWord* result = par_allocate(alloc_region, min_word_size, desired_word_size, actual_word_size);
}- 继续
inline HeapWord* G1AllocRegion::par_allocate(HeapRegion* alloc_region,
size_t min_word_size,
size_t desired_word_size,
size_t* actual_word_size) {
// 结合上下文,由于是被 attempt_allocation_locked 方法内的 mutator_alloc_region 调用,所以这里 _bot_updates 是 false
if (!_bot_updates) {
// 会进到这里
return alloc_region->par_allocate_no_bot_updates(min_word_size, desired_word_size, actual_word_size);
} else {
return alloc_region->par_allocate(min_word_size, desired_word_size, actual_word_size);
}
}- 继续
inline HeapWord* HeapRegion::par_allocate_no_bot_updates(size_t min_word_size,
size_t desired_word_size,
size_t* actual_word_size) {
return par_allocate_impl(min_word_size, desired_word_size, actual_word_size);
}- 继续
inline HeapWord* G1ContiguousSpace::par_allocate_impl(size_t min_word_size,
size_t desired_word_size,
size_t* actual_size) {
do {
HeapWord* obj = top();
size_t available = pointer_delta(end(), obj);
size_t want_to_allocate = MIN2(available, desired_word_size);
if (want_to_allocate >= min_word_size) {
HeapWord* new_top = obj + want_to_allocate;
HeapWord* result = Atomic::cmpxchg(new_top, top_addr(), obj);
if (result == obj) {
*actual_size = want_to_allocate;
return obj;
}
} else {
return NULL;
}
} while (true);
}- 代码
HeapWord* G1AllocRegion::new_alloc_region_and_allocate(size_t word_size, bool force) {
HeapRegion* new_alloc_region = allocate_new_region(word_size, force);
if (new_alloc_region != NULL) {
new_alloc_region->reset_pre_dummy_top();
_used_bytes_before = new_alloc_region->used();
HeapWord* result = allocate(new_alloc_region, word_size);
OrderAccess::storestore();
update_alloc_region(new_alloc_region);
return result;
}
}- allocate_new_region()
HeapRegion* MutatorAllocRegion::allocate_new_region(size_t word_size, bool force) {
return _g1h->new_mutator_alloc_region(word_size, force);
}- new_mutator_alloc_region()
HeapRegion* G1CollectedHeap::new_mutator_alloc_region(size_t word_size,
bool force) {
bool should_allocate = g1_policy()->should_allocate_mutator_region();
if (force || should_allocate) {
HeapRegion* new_alloc_region = new_region(word_size,
false /* is_old */,
false /* do_expand */);
if (new_alloc_region != NULL) {
set_region_short_lived_locked(new_alloc_region);
_hr_printer.alloc(new_alloc_region, !should_allocate);
_verifier->check_bitmaps("Mutator Region Allocation", new_alloc_region);
_g1_policy->remset_tracker()->update_at_allocate(new_alloc_region);
return new_alloc_region;
}
}
return NULL;
}- should_allocate_mutator_region()
bool G1Policy::should_allocate_mutator_region() const {
// 当前的年轻代 region 个数
uint young_list_length = _g1h->young_regions_count();
// 年轻代的期望数量
uint young_list_target_length = _young_list_target_length;
// 没有超出期望值就为真
return young_list_length < young_list_target_length;
}- new_region()
HeapRegion* G1CollectedHeap::new_region(size_t word_size, bool is_old, bool do_expand) {
HeapRegion* res = _hrm.allocate_free_region(is_old);
if (res == NULL && do_expand && _expand_heap_after_alloc_failure) {
if (expand(word_size * HeapWordSize)) {
res = _hrm.allocate_free_region(is_old);
} else {
_expand_heap_after_alloc_failure = false;
}
}
}