ConcurrentG1RefineThread は, HotSpot の初期化時に G1CollectedHeap::initialize() の中で生成される.
ConcurrentG1RefineThread の作成は os::create_thread() 及び os::start_thread() で行われる. このため, 生成された ConcurrentG1RefineThread スレッドは java_start() から実行が開始される (See: here for details).
java_start() から始まるスレッドの起動処理では最終的に Thread::run() が呼び出される (See: here for details). ConcurrentG1RefineThread は Thread::run() をオーバーライドしているので, 実際に呼び出されるのは ConcurrentG1RefineThread::run() になる. この ConcurrentG1RefineThread::run() の中で実際の remembered set の管理処理が行われる.
ConcurrentG1RefineThread は, HotSpot の初期化時に最大数分だけ生成された後, 仕事の量に応じて動的に稼働数を変える. これは, 仕事のない ConcurrentG1RefineThread が自発的にブロックすることで実現されている. 一旦ブロックした ConcurrentG1RefineThread は, 仕事量が増加してくると他の ConcurrentG1RefineThread から, もしくは Mutator である JavaThread の Write barrier 処理から起床される.
(さらに, 仕事量が多すぎて ConcurrentG1RefineThread だけでは間に合わない場合, Mutator である通常の JavaThread も処理に加わる) (See: here for details)
稼働数を管理するために 3つの閾値が用意されている("green", "yellow", "red"). 処理は以下のようになる.
((cite: hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp))
/*
* The value of the update buffer queue length falls into one of 3 zones:
* green, yellow, red. If the value is in [0, green) nothing is
* done, the buffers are left unprocessed to enable the caching effect of the
* dirtied cards. In the yellow zone [green, yellow) the concurrent refinement
* threads are gradually activated. In [yellow, red) all threads are
* running. If the length becomes red (max queue length) the mutators start
* processing the buffers.
*
* There are some interesting cases (when G1UseAdaptiveConcRefinement
* is turned off):
* 1) green = yellow = red = 0. In this case the mutator will process all
* buffers. Except for those that are created by the deferred updates
* machinery during a collection.
* 2) green = 0. Means no caching. Can be a good way to minimize the
* amount of time spent updating rsets during a collection.
*/
int _green_zone;
int _yellow_zone;
int _red_zone;
なお, ConcurrentG1RefineThread の稼働数の増減を実現するため, 各 ConcurrentG1RefineThread はそれぞれ個別の Monitor オブジェクトを保持している (0 番目の ConcurrentG1RefineThread だけは, DirtyCardQ_CBL_mon を使用する). 各 ConcurrentG1RefineThread は, worker id が一つ小さい ConcurrentG1RefineThread によって起床される (0 番目の ConcurrentG1RefineThread だけは, write barrier 処理から起床される). (See: ConcurrentG1RefineThread) (See: here for details)
G1CollectedHeap::initialize() (See: here for details) -> ConcurrentG1Refine::ConcurrentG1Refine() -> ConcurrentG1RefineThread::ConcurrentG1RefineThread() -> ConcurrentG1RefineThread::initialize() -> ConcurrentGCThread::create_and_start() -> os::create_thread() -> (See: here for details) -> os::set_priority() -> os::start_thread() -> (See: here for details)
-> java_start() -> (See: here, here and here for details) -> ConcurrentG1RefineThread::run() -> (1) 初期化 -> ConcurrentGCThread::initialize_in_thread() (2) HotSpot の初期化が終わるまで待機する -> ConcurrentGCThread::wait_for_universe_init() (3) HotSpot が終了するまで, 以下の処理を無限ループ (1) 仕事がくるまで待機 (= Write Barrier 処理, もしくは他の ConcurrentG1RefineThread から起こされるまで待つ) (See: here for details, ConcurrentG1RefineThread::run()) -> ConcurrentG1RefineThread::wait_for_completed_buffers() (1) 処理量に応じて, ConcurrentG1RefineThread の稼働数を増減させる * 処理量が少ない場合: -> ConcurrentG1RefineThread::deactivate() * 処理量が多い場合: -> ConcurrentG1RefineThread::activate() (<= 他の ConcurrentG1RefineThread を起こす処理) (1) card の処理を行う -> DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i, int stop_at, bool during_pause) -> DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl, int worker_i, int stop_at, bool during_pause) -> DirtyCardQueueSet::get_completed_buffer() -> DirtyCardQueueSet::apply_closure_to_completed_buffer_helper() -> DirtyCardQueue::apply_closure_to_buffer() -> RefineCardTableEntryClosure::do_card_ptr() -> G1RemSet::concurrentRefineOneCard() -> ConcurrentG1Refine::cache_insert() -> G1RemSet::concurrentRefineOneCard_impl() -> HeapRegion::oops_on_card_seq_iterate_careful() (この場合のクロージャーは, check_for_refs_into_cset 引数が false なので, UpdateRSOrPushRefOopClosure を FilterOutOfRegionClosure でくるんだもの) -> oopDesc::oop_iterate() -> FilterOutOfRegionClosure::do_oop() -> FilterOutOfRegionClosure::do_oop_nv() -> UpdateRSOrPushRefOopClosure::do_oop() -> UpdateRSOrPushRefOopClosure::do_oop_work() -> G1RemSet::par_write_ref() -> HeapRegionRemSet::add_reference(OopOrNarrowOopStar from, int tid) -> OtherRegionsTable::add_reference() -> OtherRegionsTable::find_region_table() -> 新しいエントリが必要なら以下の処理を行う. -> SparsePRT::add_card() (<= これは, 成功すればここでリターン) -> RSHashTable::add_card() -> RSHashTable::entry_for_region_ind_create() -> SparsePRTEntry::add_card() -> * もういっぱいなので coarse map に追い出して確保する場合 -> OtherRegionsTable::delete_region_table() * まだ空きがある場合 -> PosParPRT::alloc() -> PosParPRT::add_reference() -> PerRegionTable::add_reference() -> PerRegionTable::add_reference_work() -> PerRegionTable::add_card_work() -> * -> BitMap::par_at_put() * -> BitMap::at_put()
See: here for details
(#Under Construction)
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
(なお, 引数などの意味は以下を参照)
((cite: hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp))
// Refine the card corresponding to "card_ptr". If "sts" is non-NULL,
// join and leave around parts that must be atomic wrt GC. (NULL means
// being done at a safepoint.)
// If check_for_refs_into_cset is true, a true result is returned
// if the given card contains oops that have references into the
// current collection set.
See: here for details
See: here for details
((cite: hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp))
virtual void do_oop(oop* p) { do_oop_nv(p); }
virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
(#Under Construction)
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.