Up Top

Memory allocation (& GC 処理) : Garbage Collection を補佐する処理 : ConcurrentMarkThread による concurrent mark 処理


Under Construction

概要(Summary)

ConcurrentMarkThread は, HotSpot の初期化時に G1CollectedHeap::initialize() の中で生成される.

ConcurrentMarkThread の作成は os::create_thread() 及び os::start_thread() で行われる. このため, 生成された ConcurrentMarkThread スレッドは java_start() から実行が開始される (See: here for details).

java_start() から始まるスレッドの起動処理では最終的に Thread::run() が呼び出される (See: here for details). ConcurrentMarkThread は Thread::run() をオーバーライドしているので, 実際に呼び出されるのは ConcurrentMarkThread::run() になる. この ConcurrentMarkThread::run() の中で実際の Concurrent Marking 処理が行われる.

処理の流れ (概要)(Execution Flows : Summary)

ConcurrentMarkThread を作成する処理

G1CollectedHeap::initialize() (See: here for details)
-> ConcurrentMarkThread::ConcurrentMarkThread()
   -> ConcurrentGCThread::create_and_start()
      -> os::create_thread()
         -> (See: here for details)
      -> os::set_priority()
      -> os::start_thread()
         -> (See: here for details)

生成された ConcurrentMarkThread 側の処理

java_start()
-> (See: here, here and here for details)
   -> ConcurrentMarkThread::run()
      -> (1) 初期化
             -> ConcurrentGCThread::initialize_in_thread()

         (2) HotSpot の初期化が終わるまで待機する
             -> ConcurrentGCThread::wait_for_universe_init()

         (3) HotSpot が終了するまで, 以下の処理を無限ループ
             (1) 次回の concurrent mark cycle が始まるまで待機 (= G1CollectedHeap::doConcurrentMark() で起こされるまで待つ)
                 -> ConcurrentMarkThread::sleepBeforeNextCycle()

             (2) Non-Generational G1GC の場合は Initial marking pause 処理を行う

                 -> VMThread::execute()
                    -> (略) (See: here for details)
                       -> VM_CGC_Operation::doit_prologue()
                       -> VM_CGC_Operation::doit()  (<= コンストラクタ引数は CMCheckpointRootsInitialClosure)
                          -> CMCheckpointRootsInitialClosure::do_void()
                             -> ConcurrentMark::checkpointRootsInitial()
                                -> SharedHeap::process_strong_roots()
                                   (なお使用するクロージャーは (Perm領域用/非Perm領域用のどちらも) CMMarkRootsClosure)
                                   -> (略) (See: )
                                      -> CMMarkRootsClosure::do_oop()
                       -> VM_CGC_Operation::doit_epilogue()

             (3) Concurrent marking 処理および Final marking pause 処理を行う. 失敗した場合は成功するまで繰り返す.

                 (1) root から辿れる範囲に対して concurrent marking 処理を行う

                     -> ConcurrentMark::markFromRoots()
                        -> ConcurrentMark::set_phase()
                        -> CMConcurrentMarkingTask::work() (<= マルチスレッドで行う場合は WorkGang::run_task() 経由で呼び出される)
                           -> CMTask::do_marking_step()
                              -> (1) SATB buffer 内のポインタを処理する

                                     -> CMTask::drain_satb_buffers()
                                        -> * multi-thread 用
                                             -> SATBMarkQueueSet::par_apply_closure_to_completed_buffer()
                                                (使用するクロージャーは CMObjectClosure)
                                                -> SATBMarkQueueSet::apply_closure_to_completed_buffer_work()
                                                   -> ObjPtrQueue::apply_closure_to_buffer()
                                                      -> CMObjectClosure::do_object()
                                                         -> CMTask::deal_with_reference()
                                                            -> CMBitMap::parMark()
                                                            -> CMTask::push()  (<= finger より前のアドレスであれば呼び出す)
                                                               -> GenericTaskQueue<E, N>::push()
                                           * single-thread 用
                                             -> SATBMarkQueueSet::apply_closure_to_completed_buffer()
                                                (使用するクロージャーは CMObjectClosure)
                                                -> SATBMarkQueueSet::apply_closure_to_completed_buffer_work()
                                                   -> (同上)
                                     -> CMTask::drain_local_queue()
                                        -> GenericTaskQueue<E, N>::pop_local()
                                        -> CMTask::scan_object()
                                           -> oopDesc::oop_iterate()
                                              -> (略)
                                                 -> CMOopClosure::do_oop()
                                                    -> CMOopClosure::do_oop_work()
                                                       -> CMTask::deal_with_reference()
                                                          -> (同上)
                                     -> CMTask::drain_global_stack()
                                        -> CMTask::get_entries_from_global_stack()
                                        -> CMTask::drain_local_queue()
                                           -> (同上)

                                 (2) Region stack 内のポインタを処理する

                                     -> CMTask::drain_region_stack()
                                        -> ConcurrentMark::region_stack_pop_lock_free()
                                        -> BitMap::iterate()
                                           (使用するクロージャーは CMBitMapClosure)
                                           -> CMBitMapClosure::do_bit()
                                              -> CMTask::scan_object()
                                                 -> (同上)
                                              -> CMTask::drain_local_queue()
                                                 -> (同上)
                                              -> CMTask::drain_global_stack()
                                                 -> (同上)
                                     -> CMTask::drain_local_queue()
                                        -> (同上)
                                     -> CMTask::drain_global_stack()
                                        -> (同上)

                                 (3) 未処理の HeapRegion に対して, CMBitMapClosure での処理を行っていく.
                                     (以下の処理を先頭の HeapRegion から最後の HeapRegion まで行う.
                                      なお, 他の CMTask が既に処理した HeapRegion は処理しない)

                                     -> BitMap::iterate()
                                        (使用するクロージャーは CMBitMapClosure)
                                        -> CMBitMapClosure::do_bit()
                                           -> (同上)
                                     -> CMTask::drain_local_queue()
                                     -> CMTask::drain_global_stack()
                                     -> ConcurrentMark::claim_region()

                                 (3) SATB buffer 内のポインタを処理する

                                     -> CMTask::drain_satb_buffers()

                                 (3)

                                     -> CMTask::drain_local_queue()
                                     -> CMTask::drain_global_stack()

                 (2) Final marking pause 処理を行う

                     -> VMThread::execute()
                        -> (略) (See: here for details)
                           -> VM_CGC_Operation::doit_prologue()
                           -> VM_CGC_Operation::doit()  (<= コンストラクタ引数は CMCheckpointRootsInitialClosure)
                              -> CMCheckpointRootsFinalClosure::do_void()
                                 -> ConcurrentMark::checkpointRootsFinal()
                                    -> (1) root から辿れる範囲に対して Final marking 処理を行う
                                           -> ConcurrentMark::checkpointRootsFinalWork()
                                              -> ConcurrentMark::set_phase()
                                              -> CMRemarkTask::work() (<= マルチスレッドで行う場合は WorkGang::run_task() 経由で呼び出される)
                                                 -> CMTask::do_marking_step()
                                                    -> (同上)

                                       (1) 以上の処理で見つかった参照オブジェクト(java.lang.ref オブジェクト)の処理を行う
                                           -> ConcurrentMark::weakRefsWork()
                                              -> ReferenceProcessor::process_discovered_references()
                                                 (なお使用するクロージャーおよびAbstractRefProcTaskExecutorは,
                                                 G1CMIsAliveClosure, G1CMKeepAliveClosure, G1CMDrainMarkingStackClosure, G1RefProcTaskExecutor)
                                                 -> (See: here for details)

                                                    なお, 並列処理する場合はこの中で G1RefProcTaskExecutor が使用される.
                                                    G1RefProcTaskExecutor は, ReferenceProcessor::process_discovered_references() 内で
                                                    RefProcPhase1Task, RefProcPhase2Task, RefProcPhase3Task に対して以下のように呼び出される

                                                    -> G1RefProcTaskExecutor::execute()
                                                       -> G1RefProcTaskProxy::work() (<= WorkGang::run_task() 経由で呼び出される)
                                                          (なお使用するクロージャーは,
                                                           G1CMIsAliveClosure, G1CMParKeepAliveAndDrainClosure, G1CMParDrainMarkingStackClosure)
                                                          -> AbstractRefProcTaskExecutor::ProcessTask::work()
                                                             -> (実際には各サブクラスがオーバーライドしたメソッドが呼び出される
                                                                 (See: RefProcPhase1Task::work(), RefProcPhase2Task::work(), RefProcPhase3Task::work()))
                                                                (See: here for details)

                                              -> ReferenceProcessor::enqueue_discovered_references()
                                                 (なお使用するAbstractRefProcTaskExecutorは, G1RefProcTaskExecutor)
                                                 -> (See: here for details)
                                              -> StringTable::unlink()
                                                 (なお使用するクロージャーは G1CMIsAliveClosure)
                                              -> SymbolTable::unlink()

                                       (1) 後片付け
                                           -> SATBMarkQueueSet::set_active_all_threads()

                           -> VM_CGC_Operation::doit_epilogue()

             (4) Live Data Counting & Cleanup 処理を行う.

                 -> VMThread::execute()
                    -> (略) (See: here for details)
                       -> VM_CGC_Operation::doit_prologue()
                       -> VM_CGC_Operation::doit()  (<= コンストラクタ引数は CMCleanUp)
                          -> CMCleanUp::do_void()
                             -> ConcurrentMark::cleanup()
                                -> (1) Live Data Counting 処理を行う.
                                       -> G1ParFinalCountTask::work() (<= マルチスレッドで行う場合は WorkGang::run_task() 経由で呼び出される)
                                          -> * マルチスレッドで処理する場合
                                               -> G1CollectedHeap::heap_region_par_iterate_chunked()
                                                  (なお使用するクロージャーは CalcLiveObjectsClosure)
                                                  -> CalcLiveObjectsClosure::doHeapRegion()
                                             * シングルスレッドで処理する場合
                                               -> G1CollectedHeap::heap_region_iterate()
                                                  (なお使用するクロージャーは CalcLiveObjectsClosure)
                                                  -> HeapRegionSeq::iterate()
                                                     -> HeapRegionSeq::iterate_from()
                                                        -> CalcLiveObjectsClosure::doHeapRegion()

                                   (2) next marking bitmap と prev marking bitmap を入れ替える
                                       -> ConcurrentMark::swapMarkBitMaps()

                                   (3) Cleanup 処理を行う.
                                       -> G1ParNoteEndTask::work() (<= マルチスレッドで行う場合は WorkGang::run_task() 経由で呼び出される)
                                          -> * マルチスレッドで処理する場合
                                               -> G1CollectedHeap::heap_region_par_iterate_chunked()
                                                  (なお使用するクロージャーは G1NoteEndOfConcMarkClosure)
                                                  -> G1NoteEndOfConcMarkClosure::doHeapRegion()
                                                     -> HeapRegion::note_end_of_marking()
                                                     -> G1CollectedHeap::free_region_if_empty()
                                             * シングルスレッドで処理する場合
                                               -> G1CollectedHeap::heap_region_iterate()
                                                  (なお使用するクロージャーは G1NoteEndOfConcMarkClosure)
                                                  -> HeapRegionSeq::iterate()
                                                     -> HeapRegionSeq::iterate_from()
                                                        -> G1NoteEndOfConcMarkClosure::doHeapRegion()
                                                           -> (同上)
                                          -> G1CollectedHeap::update_sets_after_freeing_regions()
                                          -> HeapRegionLinkedList::add_as_tail()
                                          -> HeapRegionRemSet::finish_cleanup_task()

                       -> VM_CGC_Operation::doit_epilogue()

             (5) Cleanup 処理で空の HeapRegion が見つかっていた場合は処理を行う

                 -> ConcurrentMark::completeCleanup()
                 -> G1CollectedHeap::reset_free_regions_coming()

             (6) _nextMarkBitMap をクリアする

                 -> ConcurrentMark::clearNextBitmap()

             (7) (Full GC の完了を待っているスレッドがいれば) 起床させておく (See: VM_G1IncCollectionPause::doit_epilogue())

                 -> G1CollectedHeap::increment_full_collections_completed()

         (7) (メインループが終わったので) 終了する
             -> ConcurrentGCThread::terminate()

備考(Notes)

なお, CMTask::do_marking_step() 部分の処理の流れは以下のようになる.

処理の流れ (詳細)(Execution Flows : Details)

ConcurrentMarkThread::ConcurrentMarkThread()

See: here for details

ConcurrentGCThread::ConcurrentGCThread()

(#Under Construction)

ConcurrentGCThread::create_and_start()

See: here for details

ConcurrentMarkThread::run()

See: here for details

ConcurrentGCThread::initialize_in_thread()

See: here for details

ConcurrentGCThread::wait_for_universe_init()

See: here for details

ConcurrentMarkThread::sleepBeforeNextCycle()

See: here for details

ConcurrentMarkThread::set_in_progress()

See: here for details

ConcurrentMarkThread::clear_started()

See: here for details

VM_CGC_Operation::doit_prologue()

See: here for details

VM_CGC_Operation::doit()

See: here for details

VM_CGC_Operation::doit_epilogue()

See: here for details

CMCheckpointRootsInitialClosure::do_void()

See: here for details

ConcurrentMark::checkpointRootsInitial()

See: here for details

CMMarkRootsClosure::do_oop()

(#Under Construction)

ConcurrentMark::markFromRoots()

See: here for details

ConcurrentMark::set_phase()

(#Under Construction)

CMConcurrentMarkingTask::work()

See: here for details

ConcurrentGCThread::stsJoin()

See: here for details

CMTask::do_marking_step()

See: here for details

CMTask::drain_satb_buffers()

See: here for details

CMTask::regular_clock_call()

See: here for details

SATBMarkQueueSet::par_apply_closure_to_completed_buffer()

See: here for details

SATBMarkQueueSet::apply_closure_to_completed_buffer()

See: here for details

SATBMarkQueueSet::apply_closure_to_completed_buffer_work()

See: here for details

CMObjectClosure::do_object()

See: here for details

CMTask::deal_with_reference()

See: here for details

CMBitMap::parMark()

See: here for details

BitMap::par_set_bit()

See: here for details

CMTask::drain_local_queue()

See: here for details

CMTask::scan_object()

See: here for details

CMOopClosure::do_oop()

CMOopClosure::do_oop_work() を呼び出すだけ.

    ((cite: hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp))
      virtual void do_oop(narrowOop* p) { do_oop_work(p); }
      virtual void do_oop(      oop* p) { do_oop_work(p); }

CMOopClosure::do_oop_work()

See: here for details

CMTask::drain_global_stack()

See: here for details

CMTask::get_entries_from_global_stack()

See: here for details

CMTask::drain_region_stack()

See: here for details

ConcurrentMark::region_stack_pop_lock_free()

(#Under Construction)

CMBitMapClosure::do_bit()

See: here for details

ConcurrentGCThread::stsLeave()

See: here for details

G1MMUTracker::when_ms()

(#Under Construction)

CMCheckpointRootsFinalClosure::do_void()

See: here for details

ConcurrentMark::checkpointRootsFinal()

See: here for details

ConcurrentMark::checkpointRootsFinalWork()

See: here for details

CMRemarkTask::work()

See: here for details

ConcurrentMark::weakRefsWork()

See: here for details

ConcurrentMark::set_non_marking_state()

See: here for details

SATBMarkQueueSet::set_active_all_threads()

(#Under Construction)

CMCleanUp:do_void()

See: here for details

ConcurrentMark::cleanup()

See: here for details

HeapRegionRemSet::reset_for_cleanup_tasks()

See: here for details

SparsePRT::reset_for_cleanup_tasks()

See: here for details

G1ParFinalCountTask::work()

See: here for details

G1CollectedHeap::heap_region_par_iterate_chunked()

See: here for details

CalcLiveObjectsClosure::doHeapRegion()

See: here for details

ConcurrentMark::swapMarkBitMaps()

See: here for details

G1ParNoteEndTask::work()

See: here for details

G1NoteEndOfConcMarkClosure::doHeapRegion()

See: here for details

HeapRegion::note_end_of_marking()

See: here for details

G1CollectedHeap::free_region_if_empty()

See: here for details

HeapRegionRemSet::do_cleanup_work()

See: here for details

OtherRegionsTable::do_cleanup_work()

See: here for details

SparsePRT::do_cleanup_work()

See: here for details

SparsePRT::should_be_on_expanded_list()

See: here for details

SparsePRT::expanded()

(単なる getter method)

    ((cite: hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp))
      bool expanded() { return _expanded; }

G1CollectedHeap::update_sets_after_freeing_regions()

See: here for details

HeapRegionLinkedList::add_as_tail()

(#Under Construction)

HeapRegionRemSet::finish_cleanup_task()

See: here for details

SparsePRT::finish_cleanup_task()

See: here for details

G1CollectedHeap::reset_free_regions_coming()

See: here for details

ConcurrentMark::clearNextBitmap()

See: here for details

ConcurrentMark::do_yield_check()

See: here for details

ConcurrentMark::should_yield()

See: here for details

ConcurrentGCThread::should_yield()

SuspendibleThreadSet::should_yield() を呼び出すだけ.

    ((cite: hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp))
      bool should_yield() { return _sts.should_yield(); }

SuspendibleThreadSet::should_yield()

    ((cite: hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp))
      // Returns "true" iff an suspension is in progress.
      bool should_yield() { return _async_stop; }

ConcurrentMarkThread::yield()

See: here for details

SuspendibleThreadSet::yield()

See: here for details


This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.