hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
// This method contains no policy. You should probably
// be calling invoke() instead.
void PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
assert(ref_processor() != NULL, "Sanity");
{- -------------------------------------------
(1) もし GC_locker によって GC が禁止されていれば, ここでリターン.
---------------------------------------- -}
if (GC_locker::check_active_before_gc()) {
return;
}
{- -------------------------------------------
(1) (変数宣言など)
(これらはトレース出力用のために使われる)
---------------------------------------- -}
TimeStamp marking_start;
TimeStamp compaction_start;
TimeStamp collection_exit;
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
ParallelScavengeHeap* heap = gc_heap();
GCCause::Cause gc_cause = heap->gc_cause();
PSYoungGen* young_gen = heap->young_gen();
PSOldGen* old_gen = heap->old_gen();
PSPermGen* perm_gen = heap->perm_gen();
PSAdaptiveSizePolicy* size_policy = heap->size_policy();
// The scope of casr should end after code that can change
// CollectorPolicy::_should_clear_all_soft_refs.
ClearedAllSoftRefs casr(maximum_heap_compaction,
heap->collector_policy());
{- -------------------------------------------
(1) (デバッグ用の処理)
(ZapUnusedHeapArea オプションが指定されている場合は ...#TODO)
---------------------------------------- -}
if (ZapUnusedHeapArea) {
// Save information needed to minimize mangling
heap->record_gen_tops_before_GC();
}
{- -------------------------------------------
(1) (トレース出力)
(See: CollectedHeap::pre_full_gc_dump())
---------------------------------------- -}
heap->pre_full_gc_dump();
{- -------------------------------------------
(1) (トレース出力用の処理)
(PSParallelCompact::print_phases() の値を設定しておく)
---------------------------------------- -}
_print_phases = PrintGCDetails && PrintParallelOldGCPhaseTimes;
{- -------------------------------------------
(1) PSParallelCompact::pre_compact() を呼んで, GC のための前準備を行う.
---------------------------------------- -}
// Make sure data structures are sane, make the heap parsable, and do other
// miscellaneous bookkeeping.
PreGCValues pre_gc_values;
pre_compact(&pre_gc_values);
{- -------------------------------------------
(1) VMThread 用の ParCompactionManager オブジェクトを取得する.
---------------------------------------- -}
// Get the compaction manager reserved for the VM thread.
ParCompactionManager* const vmthread_cm =
ParCompactionManager::manager_array(gc_task_manager()->workers());
{- -------------------------------------------
(1) (トレース出力) (See: AdaptiveSizePolicyOutput)
---------------------------------------- -}
// Place after pre_compact() where the number of invocations is incremented.
AdaptiveSizePolicyOutput(size_policy, heap->total_collections());
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
{
ResourceMark rm;
HandleMark hm;
const bool is_system_gc = gc_cause == GCCause::_java_lang_system_gc;
{- -------------------------------------------
(1) (トレース出力用の処理) & (トレース出力)
---------------------------------------- -}
// This is useful for debugging but don't change the output the
// the customer sees.
const char* gc_cause_str = "Full GC";
if (is_system_gc && PrintGCDetails) {
gc_cause_str = "Full GC (System)";
}
gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
TraceTime t1(gc_cause_str, PrintGC, !PrintGCDetails, gclog_or_tty);
TraceCollectorStats tcs(counters());
{- -------------------------------------------
(1) (トレース出力用の処理) (DTrace のフック点) (JMM のフック点)
(See: TraceMemoryManagerStats)
---------------------------------------- -}
TraceMemoryManagerStats tms(true /* Full GC */,gc_cause);
{- -------------------------------------------
(1) (トレース出力用の処理)
(Old 領域の GC にかかる時間を記録)
---------------------------------------- -}
if (TraceGen1Time) accumulated_time()->start();
{- -------------------------------------------
(1) AdaptiveSizePolicy を更新する
(ここから先が GC 処理の時間になるので,
AdaptiveSizePolicy::major_collection_begin() を呼んで
PSAdaptiveSizePolicy オブジェクト内の非GC時間情報を更新)
---------------------------------------- -}
// Let the size policy know we're starting
size_policy->major_collection_begin();
{- -------------------------------------------
(1) フレーム中の bcp (byte code pointer, バイトコードを指すポインタ) を格納している箇所については
GC によって methodOop が移動すると値が不正になってしまうので,
Threads::gc_prologue() を呼んで
フレーム中の bcp を bci (byte code index, そのバイトコードのメソッド先頭からのオフセット値) に変えておく.
(なお, CodeCache::gc_prologue()の方は, 単なる(assert) (See: CodeCache::gc_prologue()))
---------------------------------------- -}
// When collecting the permanent generation methodOops may be moving,
// so we either have to flush all bcp data or convert it into bci.
CodeCache::gc_prologue();
Threads::gc_prologue();
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
NOT_PRODUCT(ref_processor()->verify_no_references_recorded());
{- -------------------------------------------
(1) #ifdef COMPILER2 の場合には, (これから GC を行うので) DerivedPointerTable の値をリセットしておく.
(See: DerivedPointerTable)
---------------------------------------- -}
COMPILER2_PRESENT(DerivedPointerTable::clear());
{- -------------------------------------------
(1) これから GC を行うので, ReferenceProcessor オブジェクトをリセットしておく.
---------------------------------------- -}
ref_processor()->enable_discovery();
ref_processor()->setup_policy(maximum_heap_compaction);
{- -------------------------------------------
(1) ?? (この変数はこの後使われてないが...)
---------------------------------------- -}
bool marked_for_unloading = false;
{- -------------------------------------------
(1) (トレース出力用の処理)
(GC 開始時の時刻を計測しておく)
---------------------------------------- -}
marking_start.update();
{- -------------------------------------------
(1) PSParallelCompact::marking_phase() を呼び出して, 生きているオブジェクト全てに印(mark)を付ける.
---------------------------------------- -}
marking_phase(vmthread_cm, maximum_heap_compaction);
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
#ifndef PRODUCT
if (TraceParallelOldGCMarkingPhase) {
gclog_or_tty->print_cr("marking_phase: cas_tries %d cas_retries %d "
"cas_by_another %d",
mark_bitmap()->cas_tries(), mark_bitmap()->cas_retries(),
mark_bitmap()->cas_by_another());
}
#endif // #ifndef PRODUCT
{- -------------------------------------------
(1) PSParallelCompact::summary_phase() を呼んで, #TODO
---------------------------------------- -}
bool max_on_system_gc = UseMaximumCompactionOnSystemGC && is_system_gc;
summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);
{- -------------------------------------------
(1) #ifdef COMPILER2 の場合, DerivedPointerTable::set_active() を呼んで,
DerivedPointerTable にこれ以上ポインタが登録されないようにしておく.
---------------------------------------- -}
COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
COMPILER2_PRESENT(DerivedPointerTable::set_active(false));
{- -------------------------------------------
(1) PSParallelCompact::adjust_roots() を呼んで,
全ての strong root 内のポインタをコンパクション後の新しいアドレスに修正する.
---------------------------------------- -}
// adjust_roots() updates Universe::_intArrayKlassObj which is
// needed by the compaction for filling holes in the dense prefix.
adjust_roots();
{- -------------------------------------------
(1) (トレース出力用の処理)
(コンパクション開始時の時刻を計測しておく)
---------------------------------------- -}
compaction_start.update();
{- -------------------------------------------
(1) PSParallelCompact::compact_perm() と PSParallelCompact::compact() を呼んで,
それぞれ Perm 領域内, New/Old 領域内の各 live object について
新しいアドレスに移動させ, それらの中にあるポインタを新しいアドレスに修正する.
---------------------------------------- -}
// Does the perm gen always have to be done serially because
// klasses are used in the update of an object?
compact_perm(vmthread_cm);
compact();
{- -------------------------------------------
(1) PSParallelCompact::post_compact() を呼んで, GC 処理の後片付けを行う
---------------------------------------- -}
// Reset the mark bitmap, summary data, and do other bookkeeping. Must be
// done before resizing.
post_compact();
{- -------------------------------------------
(1) AdaptiveSizePolicy を更新する
(ここまでが GC 処理の時間になるので,
AdaptiveSizePolicy::major_collection_end() を呼んで,
PSAdaptiveSizePolicy オブジェクト内の GC 時間情報を更新する)
---------------------------------------- -}
// Let the size policy know we're done
size_policy->major_collection_end(old_gen->used_in_bytes(), gc_cause);
{- -------------------------------------------
(1) GC 結果に基づいて領域長を調整しておく.
(See: GC Ergonomics)
---------------------------------------- -}
if (UseAdaptiveSizePolicy) {
if (PrintAdaptiveSizePolicy) {
gclog_or_tty->print("AdaptiveSizeStart: ");
gclog_or_tty->stamp();
gclog_or_tty->print_cr(" collection: %d ",
heap->total_collections());
if (Verbose) {
gclog_or_tty->print("old_gen_capacity: %d young_gen_capacity: %d"
" perm_gen_capacity: %d ",
old_gen->capacity_in_bytes(), young_gen->capacity_in_bytes(),
perm_gen->capacity_in_bytes());
}
}
// Don't check if the size_policy is ready here. Let
// the size_policy check that internally.
if (UseAdaptiveGenerationSizePolicyAtMajorCollection &&
((gc_cause != GCCause::_java_lang_system_gc) ||
UseAdaptiveSizePolicyWithSystemGC)) {
// Calculate optimal free space amounts
assert(young_gen->max_size() >
young_gen->from_space()->capacity_in_bytes() +
young_gen->to_space()->capacity_in_bytes(),
"Sizes of space in young gen are out-of-bounds");
size_t max_eden_size = young_gen->max_size() -
young_gen->from_space()->capacity_in_bytes() -
young_gen->to_space()->capacity_in_bytes();
size_policy->compute_generation_free_space(
young_gen->used_in_bytes(),
young_gen->eden_space()->used_in_bytes(),
old_gen->used_in_bytes(),
perm_gen->used_in_bytes(),
young_gen->eden_space()->capacity_in_bytes(),
old_gen->max_gen_size(),
max_eden_size,
true /* full gc*/,
gc_cause,
heap->collector_policy());
heap->resize_old_gen(
size_policy->calculated_old_free_size_in_bytes());
// Don't resize the young generation at an major collection. A
// desired young generation size may have been calculated but
// resizing the young generation complicates the code because the
// resizing of the old generation may have moved the boundary
// between the young generation and the old generation. Let the
// young generation resizing happen at the minor collections.
}
if (PrintAdaptiveSizePolicy) {
gclog_or_tty->print_cr("AdaptiveSizeStop: collection: %d ",
heap->total_collections());
}
}
{- -------------------------------------------
(1) (プロファイル情報の記録) (See: PSGCAdaptivePolicyCounters)
---------------------------------------- -}
if (UsePerfData) {
PSGCAdaptivePolicyCounters* const counters = heap->gc_policy_counters();
counters->update_counters();
counters->update_old_capacity(old_gen->capacity_in_bytes());
counters->update_young_capacity(young_gen->capacity_in_bytes());
}
{- -------------------------------------------
(1) ParallelScavengeHeap::resize_all_tlabs() で, 各スレッドの TLAB の大きさを最適に調整しておく.
---------------------------------------- -}
heap->resize_all_tlabs();
{- -------------------------------------------
(1) Perm 領域内のゴミも回収したので,
PSPermGen::compute_new_size() を呼んで, 大きさを最適に調整しておく.
---------------------------------------- -}
// We collected the perm gen, so we'll resize it here.
perm_gen->compute_new_size(pre_gc_values.perm_gen_used());
{- -------------------------------------------
(1) (トレース出力用の処理)
(Old 領域の GC にかかる時間を記録)
---------------------------------------- -}
if (TraceGen1Time) accumulated_time()->stop();
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (PrintGC) {
if (PrintGCDetails) {
// No GC timestamp here. This is after GC so it would be confusing.
young_gen->print_used_change(pre_gc_values.young_gen_used());
old_gen->print_used_change(pre_gc_values.old_gen_used());
heap->print_heap_change(pre_gc_values.heap_used());
// Print perm gen last (print_heap_change() excludes the perm gen).
perm_gen->print_used_change(pre_gc_values.perm_gen_used());
} else {
heap->print_heap_change(pre_gc_values.heap_used());
}
}
{- -------------------------------------------
(1) (プロファイル情報の記録)(JMM 用) (See: MemoryUsage)
及び (JMM のフック点) でもある (See: LowMemoryDetector)
---------------------------------------- -}
// Track memory usage and detect low memory
MemoryService::track_memory_usage();
{- -------------------------------------------
(1) ParallelScavengeHeap::update_counters()を呼んで, (プロファイル情報の記録)を行う.
(See: SpaceCounter, PSGenerationCounters)
---------------------------------------- -}
heap->update_counters();
}
{- -------------------------------------------
(1) (デバッグ用の処理) (#ifdef ASSERT 時にのみ実行)
---------------------------------------- -}
#ifdef ASSERT
for (size_t i = 0; i < ParallelGCThreads + 1; ++i) {
ParCompactionManager* const cm =
ParCompactionManager::manager_array(int(i));
assert(cm->marking_stack()->is_empty(), "should be empty");
assert(cm->region_stack()->is_empty(), "should be empty");
assert(cm->revisit_klass_stack()->is_empty(), "should be empty");
}
#endif // ASSERT
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
if (VerifyAfterGC && heap->total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
gclog_or_tty->print(" VerifyAfterGC:");
Universe::verify(false);
}
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
// Re-verify object start arrays
if (VerifyObjectStartArray &&
VerifyAfterGC) {
old_gen->verify_object_start_array();
perm_gen->verify_object_start_array();
}
{- -------------------------------------------
(1) (デバッグ用の処理)
(ZapUnusedHeapArea オプションが指定されている場合は ...#TODO)
---------------------------------------- -}
if (ZapUnusedHeapArea) {
old_gen->object_space()->check_mangled_unused_area_complete();
perm_gen->object_space()->check_mangled_unused_area_complete();
}
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
NOT_PRODUCT(ref_processor()->verify_no_references_recorded());
{- -------------------------------------------
(1) (トレース出力用の処理)
(GC 終了時の時刻を計測しておく)
---------------------------------------- -}
collection_exit.update();
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (PrintHeapAtGC) {
Universe::print_heap_after_gc();
}
if (PrintGCTaskTimeStamps) {
gclog_or_tty->print_cr("VM-Thread " INT64_FORMAT " " INT64_FORMAT " "
INT64_FORMAT,
marking_start.ticks(), compaction_start.ticks(),
collection_exit.ticks());
gc_task_manager()->print_task_time_stamps();
}
{- -------------------------------------------
(1) (トレース出力)
(See: CollectedHeap::post_full_gc_dump())
---------------------------------------- -}
heap->post_full_gc_dump();
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
#ifdef TRACESPINNING
ParallelTaskTerminator::print_termination_counts();
#endif
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.