hotspot/src/share/vm/memory/defNewGeneration.cpp
void DefNewGeneration::collect(bool full,
bool clear_all_soft_refs,
size_t size,
bool is_tlab) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(full || size > 0, "otherwise we don't want to collect");
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
GenCollectedHeap* gch = GenCollectedHeap::heap();
{- -------------------------------------------
(1)
---------------------------------------- -}
_next_gen = gch->next_gen(this);
assert(_next_gen != NULL,
"This must be the youngest gen, and not the only gen");
{- -------------------------------------------
(1) もし次の世代の空き容量が十分でなければ, promotion が失敗する恐れがあるため, GC を諦める.
その場合は, ここでリターン.
---------------------------------------- -}
// If the next generation is too full to accomodate promotion
// from this generation, pass on collection; let the next generation
// do it.
if (!collection_attempt_is_safe()) {
if (Verbose && PrintGCDetails) {
gclog_or_tty->print(" :: Collection attempt not safe :: ");
}
gch->set_incremental_collection_failed(); // Slight lie: we did not even attempt one
return;
}
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(to()->is_empty(), "Else not collection_attempt_is_safe");
{- -------------------------------------------
(1)
---------------------------------------- -}
init_assuming_no_promotion_failure();
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
TraceTime t1("GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
// Capture heap used before collection (for printing).
size_t gch_prev_used = gch->used();
{- -------------------------------------------
(1) (デバッグ用の処理)
(See: SpecializationStats)
---------------------------------------- -}
SpecializationStats::clear();
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
// These can be shared for all code paths
IsAliveClosure is_alive(this);
ScanWeakRefClosure scan_weak_ref(this);
{- -------------------------------------------
(1) これから GC を行うので ageTable をリセットしておく.
---------------------------------------- -}
age_table()->clear();
{- -------------------------------------------
(1) ContiguousSpace::clear() で top 位置を空の位置(= bottom())に戻す.
(なお, ZapUnusedHeapArea オプションが指定されていれば,
未使用になった領域の mangle 処理も行っている模様)
---------------------------------------- -}
to()->clear(SpaceDecorator::Mangle);
{- -------------------------------------------
(1)
---------------------------------------- -}
gch->rem_set()->prepare_for_younger_refs_iterate(false);
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(gch->no_allocs_since_save_marks(0),
"save marks have not been newly set.");
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
// Not very pretty.
CollectorPolicy* cp = gch->collector_policy();
FastScanClosure fsc_with_no_gc_barrier(this, false);
FastScanClosure fsc_with_gc_barrier(this, true);
set_promo_failure_scan_stack_closure(&fsc_with_no_gc_barrier);
FastEvacuateFollowersClosure evacuate_followers(gch, _level, this,
&fsc_with_no_gc_barrier,
&fsc_with_gc_barrier);
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(gch->no_allocs_since_save_marks(0),
"save marks have not been newly set.");
{- -------------------------------------------
(1) まず, GenCollectedHeap::gen_process_strong_roots() を呼び出して
root から参照されているオブジェクトを全て処理する.
---------------------------------------- -}
gch->gen_process_strong_roots(_level,
true, // Process younger gens, if any,
// as strong roots.
true, // activate StrongRootsScope
false, // not collecting perm generation.
SharedHeap::SO_AllClasses,
&fsc_with_no_gc_barrier,
true, // walk *all* scavengable nmethods
&fsc_with_gc_barrier);
{- -------------------------------------------
(1) 次に, FastEvacuateFollowersClosure::do_void() を呼び出して,
処理したオブジェクトから再帰的にたどれる範囲についても全て処理する.
---------------------------------------- -}
// "evacuate followers".
evacuate_followers.do_void();
{- -------------------------------------------
(1) ReferenceProcessor::process_discovered_references() を呼び出して,
上の処理中に発見された参照オブジェクト(java.lang.ref オブジェクト) の処理を行う.
---------------------------------------- -}
FastKeepAliveClosure keep_alive(this, &scan_weak_ref);
ReferenceProcessor* rp = ref_processor();
rp->setup_policy(clear_all_soft_refs);
rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers,
NULL);
{- -------------------------------------------
(1) もし GC 処理が失敗していなければ, GC の後始末を行う
(survivor space (from と to) の入れ替え, tenuring_threshold の更新, etc)
---------------------------------------- -}
if (!promotion_failed()) {
// Swap the survivor spaces.
eden()->clear(SpaceDecorator::Mangle);
from()->clear(SpaceDecorator::Mangle);
if (ZapUnusedHeapArea) {
// This is now done here because of the piece-meal mangling which
// can check for valid mangling at intermediate points in the
// collection(s). When a minor collection fails to collect
// sufficient space resizing of the young generation can occur
// an redistribute the spaces in the young generation. Mangle
// here so that unzapped regions don't get distributed to
// other spaces.
to()->mangle_unused_area();
}
{- -------------------------------------------
(1.1) DefNewGeneration::swap_spaces() で To 領域と From 領域を入れ替える.
---------------------------------------- -}
swap_spaces();
{- -------------------------------------------
(1.1) (assert)
---------------------------------------- -}
assert(to()->is_empty(), "to space should be empty now");
{- -------------------------------------------
(1.1) 新しい tenuring_threshold を計算して, フィールドにセットする.
---------------------------------------- -}
// Set the desired survivor size to half the real survivor space
_tenuring_threshold =
age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize);
{- -------------------------------------------
(1.1) GC が成功したので, gc_overhead_limit_count の値は 0 にリセットしておく.
(See: UseGCOverheadLimit)
---------------------------------------- -}
// A successful scavenge should restart the GC time limit count which is
// for full GC's.
AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
size_policy->reset_gc_overhead_limit_count();
{- -------------------------------------------
(1.1) (トレース出力)
---------------------------------------- -}
if (PrintGC && !PrintGCDetails) {
gch->print_heap_change(gch_prev_used);
}
{- -------------------------------------------
(1.1) (assert)
---------------------------------------- -}
assert(!gch->incremental_collection_failed(), "Should be clear");
{- -------------------------------------------
(1) 逆に, もし GC 処理中に何か失敗していれば,
状態を修復した後, 後始末を行う.
---------------------------------------- -}
} else {
{- -------------------------------------------
(1.1) (assert)
---------------------------------------- -}
assert(_promo_failure_scan_stack.is_empty(), "post condition");
{- -------------------------------------------
(1.1)
---------------------------------------- -}
_promo_failure_scan_stack.clear(true); // Clear cached segments.
{- -------------------------------------------
(1.1) DefNewGeneration::remove_forwarding_pointers() を呼んで,
各オブジェクトの mark フィールドを修復する.
---------------------------------------- -}
remove_forwarding_pointers();
{- -------------------------------------------
(1.1) (トレース出力)
---------------------------------------- -}
if (PrintGCDetails) {
gclog_or_tty->print(" (promotion failed) ");
}
{- -------------------------------------------
(1.1) DefNewGeneration::swap_spaces() で To 領域と From 領域を入れ替え,
---------------------------------------- -}
// Add to-space to the list of space to compact
// when a promotion failure has occurred. In that
// case there can be live objects in to-space
// as a result of a partial evacuation of eden
// and from-space.
swap_spaces(); // For uniformity wrt ParNewGeneration.
from()->set_next_compaction_space(to());
gch->set_incremental_collection_failed();
{- -------------------------------------------
(1.1) この後の処理で分かるよう, GC が失敗したことを記録しておく.
---------------------------------------- -}
// Inform the next generation that a promotion failure occurred.
_next_gen->promotion_failure_occurred();
{- -------------------------------------------
(1.1) (デバッグ用の処理) (NOT_PRODUCT 時にのみ実行)
---------------------------------------- -}
// Reset the PromotionFailureALot counters.
NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
}
{- -------------------------------------------
(1)
---------------------------------------- -}
// set new iteration safe limit for the survivor spaces
from()->set_concurrent_iteration_safe_limit(from()->top());
to()->set_concurrent_iteration_safe_limit(to()->top());
{- -------------------------------------------
(1) (デバッグ用の処理)
(See: SpecializationStats)
---------------------------------------- -}
SpecializationStats::print();
{- -------------------------------------------
(1) Generation::update_time_of_last_gc() で, _time_of_last_gc フィールドを現在時刻に更新しておく.
(これは sun.misc.GC.maxObjectInspectionAge() メソッドを実現するため(だけ)の処理.
See: JVM_MaxObjectInspectionAge())
---------------------------------------- -}
update_time_of_last_gc(os::javaTimeMillis());
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.