hotspot/src/share/vm/memory/collectorPolicy.cpp
HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size,
bool is_tlab) {
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
GenCollectedHeap *gch = GenCollectedHeap::heap();
GCCauseSetter x(gch, GCCause::_allocation_failure);
HeapWord* result = NULL;
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(size != 0, "Precondition violated");
{- -------------------------------------------
(1) もし, 現在 GC が禁止されており(= GC_locker が active で), かつ
既に誰かが GC のエントリ処理を実行して GC の必要性を GC_locker に通知している場合,
(可能であれば, GenCollectorPolicy::expand_heap_and_allocate() による確保を試みた後で, )
ここでリターン.
---------------------------------------- -}
if (GC_locker::is_active_and_needs_gc()) {
// GC locker is active; instead of a collection we will attempt
// to expand the heap, if there's room for expansion.
if (!gch->is_maximal_no_gc()) {
result = expand_heap_and_allocate(size, is_tlab);
}
return result; // could be null if we are out of space
{- -------------------------------------------
(1) そうでなければ, Minor GC または Full GC を実行する.
(GenCollectedHeap::incremental_collection_will_fail() が false を返せば Minor GC を実行する.
逆に true を返せば Full GC を実行する.)
---------------------------------------- -}
} else if (!gch->incremental_collection_will_fail(false /* don't consult_young */)) {
{- -------------------------------------------
(1.1) GenCollectedHeap::do_collection() で Minor GC を実行.
---------------------------------------- -}
// Do an incremental collection.
gch->do_collection(false /* full */,
false /* clear_all_soft_refs */,
size /* size */,
is_tlab /* is_tlab */,
number_of_generations() - 1 /* max_level */);
} else {
{- -------------------------------------------
(1.1) (トレース出力)
---------------------------------------- -}
if (Verbose && PrintGCDetails) {
gclog_or_tty->print(" :: Trying full because partial may fail :: ");
}
{- -------------------------------------------
(1.1) GenCollectedHeap::do_collection() で Full GC を実行.
---------------------------------------- -}
// Try a full collection; see delta for bug id 6266275
// for the original code and why this has been simplified
// with from-space allocation criteria modified and
// such allocation moved out of the safepoint path.
gch->do_collection(true /* full */,
false /* clear_all_soft_refs */,
size /* size */,
is_tlab /* is_tlab */,
number_of_generations() - 1 /* max_level */);
}
{- -------------------------------------------
(1) GenCollectedHeap::attempt_allocation() で確保を試みる.
確保が成功したら, ここでリターン.
---------------------------------------- -}
result = gch->attempt_allocation(size, is_tlab, false /*first_only*/);
if (result != NULL) {
assert(gch->is_in_reserved(result), "result not in heap");
return result;
}
{- -------------------------------------------
(1) GenCollectorPolicy::expand_heap_and_allocate() での確保を試みる.
確保が成功したら, ここでリターン.
---------------------------------------- -}
// OK, collection failed, try expansion.
result = expand_heap_and_allocate(size, is_tlab);
if (result != NULL) {
return result;
}
{- -------------------------------------------
(1) (ここまで到達してしまったら本当にメモリが足りてない状態)
GenCollectedHeap::do_collection() でもう一度 Full GC を実行する.
(今度は soft reference は全部消すことにする. 他にもありとあらゆる手段を駆使してメモリを回収する.)
---------------------------------------- -}
// If we reach this point, we're really out of memory. Try every trick
// we can to reclaim memory. Force collection of soft references. Force
// a complete compaction of the heap. Any additional methods for finding
// free memory should be here, especially if they are expensive. If this
// attempt fails, an OOM exception will be thrown.
{
IntFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted
gch->do_collection(true /* full */,
true /* clear_all_soft_refs */,
size /* size */,
is_tlab /* is_tlab */,
number_of_generations() - 1 /* max_level */);
}
{- -------------------------------------------
(1) GenCollectedHeap::attempt_allocation() で確保を試みる.
確保が成功したら, ここでリターン.
---------------------------------------- -}
result = gch->attempt_allocation(size, is_tlab, false /* first_only */);
if (result != NULL) {
assert(gch->is_in_reserved(result), "result not in heap");
return result;
}
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(!should_clear_all_soft_refs(),
"Flag should have been handled and cleared prior to this point");
{- -------------------------------------------
(1)
---------------------------------------- -}
// What else? We might try synchronous finalization later. If the total
// space available is large enough for the allocation, then a more
// complete compaction phase than we've tried so far might be
// appropriate.
return NULL;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.