hotspot/src/share/vm/memory/referenceProcessor.cpp
void
ReferenceProcessor::process_discovered_reflist(
DiscoveredList refs_lists[],
ReferencePolicy* policy,
bool clear_referent,
BoolObjectClosure* is_alive,
OopClosure* keep_alive,
VoidClosure* complete_gc,
AbstractRefProcTaskExecutor* task_executor)
{
{- -------------------------------------------
(1) (変数宣言など)
(マルチスレッドで処理するかどうかを示す)
---------------------------------------- -}
bool mt_processing = task_executor != NULL && _processing_is_mt;
{- -------------------------------------------
(1) マルチスレッドで並列処理する場合,
参照オブジェクトの discovery 処理を行っていた時点と
この ReferenceProcessor::process_discovered_reflist() 時点で
処理スレッド数が異なる可能性がある.
そこで, ReferenceProcessor::balance_queues() を呼んで
DiscoveredList の本数を
この ReferenceProcessor::process_discovered_reflist() 内で使用するスレッド数にあわせておく.
(ついでに, DiscoveredList 間で要素数に偏りがあるかもしれないので, 要素数も平均化しておく)
---------------------------------------- -}
// If discovery used MT and a dynamic number of GC threads, then
// the queues must be balanced for correctness if fewer than the
// maximum number of queues were used. The number of queue used
// during discovery may be different than the number to be used
// for processing so don't depend of _num_q < _max_num_q as part
// of the test.
bool must_balance = _discovery_is_mt;
if ((mt_processing && ParallelRefProcBalancingEnabled) ||
must_balance) {
balance_queues(refs_lists);
}
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (PrintReferenceGC && PrintGCDetails) {
size_t total = 0;
for (int i = 0; i < _max_num_q; ++i) {
total += refs_lists[i].length();
}
gclog_or_tty->print(", %u refs", total);
}
{- -------------------------------------------
(1) 各リストに対して ReferenceProcessor::process_phase1() を呼び出し,
リスト中のそれぞれの soft reference オブジェクトについて, 消去すべきかどうかを判定する.
(この判定には ReferencePolicy オブジェクトが用いられる.)
消去しなくてもよい soft reference については, 特に処理をする必要は無いので, リストから除外される.
(また, 除外した soft reference から再帰的に辿れる範囲のオブジェクトもあわせて除外する)
なお, 上の説明の通り, この処理は処理対象が soft reference である場合のみ行われる.
(つまり, weak/phantom/final reference の場合には ReferenceProcessor::process_phase1() の処理は行われない)
処理対処が soft refernce かどうかは,
ReferencePolicy オブジェクト型の引数(以下の policy) が null かどうかで判断する.
* null でなければ(= ReferencePolicy オブジェクトが渡されてきていれば), soft reference の処理だと判断する.
* null であれば, soft reference 以外の処理だと判断する (= この phase 1 の処理はスキップされる)
なお, 以下の条件の両方が満たされる場合には, この処理はマルチスレッドを用いて並列に処理する.
* AbstractRefProcTaskExecutor 型の引数(以下の mt_processing)が null ではない
(= 有効な AbstractRefProcTaskExecutor オブジェクトが渡されている)
* この ReferenceProcessor オブジェクトの _processing_is_mt フィールドが true
(並列処理する場合には, AbstractRefProcTaskExecutor オブジェクトと RefProcPhase1Task オブジェクトが用いられる.
See: AbstractRefProcTaskExecutor, RefProcPhase1Task::work())
---------------------------------------- -}
// Phase 1 (soft refs 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.
if (policy != NULL) {
if (mt_processing) {
RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/);
task_executor->execute(phase1);
} else {
for (int i = 0; i < _max_num_q; i++) {
process_phase1(refs_lists[i], policy,
is_alive, keep_alive, complete_gc);
}
}
} else { // policy == NULL
assert(refs_lists != _discoveredSoftRefs,
"Policy must be specified for soft references.");
}
{- -------------------------------------------
(1) 各リストに対して ReferenceProcessor::process_phase2() を呼び出し,
リスト中のそれぞれの参照オブジェクトについて, その差し先が生きているかどうかを判定する.
差し先が生きている参照オブジェクトについては, 特に特殊な処理をする必要は無いので, リストから除外される.
なお, 以下の条件の両方が満たされる場合には, この処理はマルチスレッドを用いて並列に処理する.
* AbstractRefProcTaskExecutor 型の引数(以下の mt_processing)が null ではない
(= 有効な AbstractRefProcTaskExecutor オブジェクトが渡されている)
* この ReferenceProcessor オブジェクトの _processing_is_mt フィールドが true
(並列処理する場合には, AbstractRefProcTaskExecutor オブジェクトと RefProcPhase2Task オブジェクトが用いられる.
See: AbstractRefProcTaskExecutor, RefProcPhase2Task::work())
---------------------------------------- -}
// Phase 2:
// . Traverse the list and remove any refs whose referents are alive.
if (mt_processing) {
RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/);
task_executor->execute(phase2);
} else {
for (int i = 0; i < _max_num_q; i++) {
process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc);
}
}
{- -------------------------------------------
(1) 各リストに対して ReferenceProcessor::process_phase3() を呼び出し,
リストに残った参照オブジェクトおよびその差し先を live 状態にしておく
(この先 ReferenceQueue に入れて処理される場合, この時点で死んでしまうとまずいので).
(なお差し先については, dead にしてよいと指定されていた場合は
live 状態にせず, 代わりに参照オブジェクトの差し先を示すフィールドを null にしておく)
---------------------------------------- -}
// Phase 3:
// . Traverse the list and process referents as appropriate.
if (mt_processing) {
RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/);
task_executor->execute(phase3);
} else {
for (int i = 0; i < _max_num_q; i++) {
process_phase3(refs_lists[i], clear_referent,
is_alive, keep_alive, complete_gc);
}
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.