hotspot/src/share/vm/memory/referenceProcessor.cpp
なお, コメントによると 「ReferenceProcessor::process_phase*() は 1 から 3 まで全てよく似ている. (どの関数も, DiscoveredList を辿って それぞれの参照オブジェクトに対して何らかの述語を適用し, 述語の判定結果に応じてリストからの除外と何らかの処理を行う, というだけ) なのでこれらは1つにまとめた方がいいかも」 とのこと.
// NOTE: process_phase*() are largely similar, and at a high level
// merely iterate over the extant list applying a predicate to
// each of its elements and possibly removing that element from the
// list and applying some further closures to that element.
// We should consider the possibility of replacing these
// process_phase*() methods by abstracting them into
// a single general iterator invocation that receives appropriate
// closures that accomplish this work.
// (SoftReferences only) Traverse the list and remove any SoftReferences whose
// referents are not alive, but that should be kept alive for policy reasons.
// Keep alive the transitive closure of all such referents.
void
ReferenceProcessor::process_phase1(DiscoveredList& refs_list,
ReferencePolicy* policy,
BoolObjectClosure* is_alive,
OopClosure* keep_alive,
VoidClosure* complete_gc) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(policy != NULL, "Must have a non-NULL policy");
{- -------------------------------------------
(1) (以下の while 文の中で, (DiscoveredListIterator を使って)
引数で渡された DiscoveredList を最初から最後まで辿って処理を行う)
---------------------------------------- -}
DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
// Decide which softly reachable refs should be kept alive.
while (iter.has_next()) {
{- -------------------------------------------
(1) もし, soft reference の差し先が死んでいるものの
ReferencePolicy による判定で消去すべきでないと判定された場合
(= ReferencePolicy::should_clear_reference() が false の場合),
その soft reference はリストから除外する.
(ついでに, DiscoveredListIterator::make_active() でその soft reference を Active 状態に戻し,
その差し先についても DiscoveredListIterator::make_referent_alive() で mark を付けて live 状態にする)
(ついでに, 除外処理を行う際には(トレース出力)も出している)
---------------------------------------- -}
iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */));
bool referent_is_dead = (iter.referent() != NULL) && !iter.is_referent_alive();
if (referent_is_dead && !policy->should_clear_reference(iter.obj())) {
if (TraceReferenceGC) {
gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy",
iter.obj(), iter.obj()->blueprint()->internal_name());
}
// Remove Reference object from list
iter.remove();
// Make the Reference object active again
iter.make_active();
// keep the referent around
iter.make_referent_alive();
iter.move_to_next();
} else {
iter.next();
}
}
{- -------------------------------------------
(1) 引数で渡されていた VoidClosure (以下の complete_gc) を用いて,
以上の処理で mark を付けられたオブジェクトから再帰的に辿れる範囲全てにも mark を付ける
(= 再帰的な到達範囲全てを live にする).
---------------------------------------- -}
// Close the reachable set
complete_gc->do_void();
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
NOT_PRODUCT(
if (PrintGCDetails && TraceReferenceGC) {
gclog_or_tty->print_cr(" Dropped %d dead Refs out of %d "
"discovered Refs by policy list " INTPTR_FORMAT,
iter.removed(), iter.processed(), (address)refs_list.head());
}
)
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.