hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
jint G1CollectedHeap::initialize() {
{- -------------------------------------------
(1) CollectedHeap::pre_initialize() を呼んで, 初期化の前準備を行っておく.
(現状では C2 用のフィールドの初期化があるだけ)
---------------------------------------- -}
CollectedHeap::pre_initialize();
{- -------------------------------------------
(1) os::enable_vtime() を呼んで,
スレッドの "virtual time" (そのスレッドが実際に稼働していた時間) の計測機能を有効にしておく.
(といっても, 現状でこの機能が働くのは Solaris だけ. 他のプラットフォームでは何も起こらない)
---------------------------------------- -}
os::enable_vtime();
{- -------------------------------------------
(1) 以降の処理は Heap_lock で排他した状態で行う.
---------------------------------------- -}
// Necessary to satisfy locking discipline assertions.
MutexLocker x(Heap_lock);
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
// While there are no constraints in the GC code that HeapWordSize
// be any particular value, there are multiple other areas in the
// system which believe this to be true (e.g. oop->object_size in some
// cases incorrectly returns the size in wordSize units rather than
// HeapWordSize).
guarantee(HeapWordSize == wordSize, "HeapWordSize must equal wordSize");
{- -------------------------------------------
(1) (変数宣言など)
(それぞれヒープ領域の初期サイズ及び最大サイズに相当)
(なお, おかしな値だった場合は Universe::check_alignment() 内で異常終了する)
---------------------------------------- -}
size_t init_byte_size = collector_policy()->initial_heap_byte_size();
size_t max_byte_size = collector_policy()->max_heap_byte_size();
// Ensure that the sizes are properly aligned.
Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap");
Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap");
{- -------------------------------------------
(1) フィールドの初期化
---------------------------------------- -}
_cg1r = new ConcurrentG1Refine();
{- -------------------------------------------
(1) ヒープ領域として確保するサイズ, および確保場所として望ましい仮想アドレスを計算する.
---------------------------------------- -}
// Reserve the maximum.
PermanentGenerationSpec* pgs = collector_policy()->permanent_generation();
// Includes the perm-gen.
const size_t total_reserved = max_byte_size + pgs->max_size();
char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop);
{- -------------------------------------------
(1) ヒープ領域をメモリ空間上に確保する
(なお, ここではまず Young, Old, Perm の全世代分をまとめて1つの連続領域として確保する.
各 Generation 毎に分ける作業は後で行う.)
---------------------------------------- -}
ReservedSpace heap_rs(max_byte_size + pgs->max_size(),
HeapRegion::GrainBytes,
UseLargePages, addr);
{- -------------------------------------------
(1) もし UseCompressedOops オプションが指定されており, かつ指定した仮想アドレスでの領域確保が失敗していた場合は
アドレスを変えて再度確保を試みる (Universe::ZeroBasedNarrowOop).
それでもダメなら, heap base を用いる方法で確保を試みる (Universe::HeapBasedNarrowOop).
---------------------------------------- -}
if (UseCompressedOops) {
if (addr != NULL && !heap_rs.is_reserved()) {
// Failed to reserve at specified address - the requested memory
// region is taken already, for example, by 'java' launcher.
// Try again to reserver heap higher.
addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop);
ReservedSpace heap_rs0(total_reserved, HeapRegion::GrainBytes,
UseLargePages, addr);
if (addr != NULL && !heap_rs0.is_reserved()) {
// Failed to reserve at specified address again - give up.
addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop);
assert(addr == NULL, "");
ReservedSpace heap_rs1(total_reserved, HeapRegion::GrainBytes,
UseLargePages, addr);
heap_rs = heap_rs1;
} else {
heap_rs = heap_rs0;
}
}
}
{- -------------------------------------------
(1) もしヒープ領域の確保に失敗していれば, ここでリターン.
---------------------------------------- -}
if (!heap_rs.is_reserved()) {
vm_exit_during_initialization("Could not reserve enough space for object heap");
return JNI_ENOMEM;
}
{- -------------------------------------------
(1) フィールドの初期化
(なおコメントによると,
並列に動いているスレッドが (ヒープに何かが入っていると) 誤解しないように初期化するように,
とのこと
---------------------------------------- -}
// It is important to do this in a way such that concurrent readers can't
// temporarily think somethings in the heap. (I've actually seen this
// happen in asserts: DLD.)
_reserved.set_word_size(0);
_reserved.set_start((HeapWord*)heap_rs.base());
_reserved.set_end((HeapWord*)(heap_rs.base() + heap_rs.size()));
{- -------------------------------------------
(1) フィールドの初期化
---------------------------------------- -}
_expansion_regions = max_byte_size/HeapRegion::GrainBytes;
{- -------------------------------------------
(1) 確保したヒープ領域に対応する Remembered Set (CardTableRS オブジェクト) 及び
Barrier Set (G1SATBCardTableLoggingModRefBS オブジェクト) を生成する. (See: CardTableRS)
(そして, それぞれ自分の SharedHeap::_rem_set フィールド, 及び CollectedHeap::_barrier_set フィールドに格納)
もし Barrier Set の確保に失敗したら, ここでリターン.
---------------------------------------- -}
// Create the gen rem set (and barrier set) for the entire reserved region.
_rem_set = collector_policy()->create_rem_set(_reserved, 2);
set_barrier_set(rem_set()->bs());
if (barrier_set()->is_a(BarrierSet::ModRef)) {
_mr_bs = (ModRefBarrierSet*)_barrier_set;
} else {
vm_exit_during_initialization("G1 requires a mod ref bs.");
return JNI_ENOMEM;
}
{- -------------------------------------------
(1) 確保したヒープ領域に対応する Remembered Set (G1RemSet オブジェクト) を生成する. (See: G1RemSet)
(そして, 自分の _g1_rem_set フィールドに格納)
もし Remembered Set の確保に失敗したら, ここでリターン.
---------------------------------------- -}
// Also create a G1 rem set.
if (mr_bs()->is_a(BarrierSet::CardTableModRef)) {
_g1_rem_set = new G1RemSet(this, (CardTableModRefBS*)mr_bs());
} else {
vm_exit_during_initialization("G1 requires a cardtable mod ref bs.");
return JNI_ENOMEM;
}
{- -------------------------------------------
(1) 上で1つの連続領域として確保したヒープ空間を Perm とそれ以外に分ける.
(Perm gen に対応する ReservedSpace, および Perm gen 以外に対応する ReservedSpace を作成)
(さらに, Perm Gen 以外に対応する ReservedSpace の方は MemRegion 化して _g1_reserved フィールドに格納しておく)
---------------------------------------- -}
// Carve out the G1 part of the heap.
ReservedSpace g1_rs = heap_rs.first_part(max_byte_size);
_g1_reserved = MemRegion((HeapWord*)g1_rs.base(),
g1_rs.size()/HeapWordSize);
ReservedSpace perm_gen_rs = heap_rs.last_part(max_byte_size);
{- -------------------------------------------
(1) PermanentGenerationSpec::init() を呼んで CompactingPermGen を生成し,
_perm_gen フィールドにセットする.
---------------------------------------- -}
_perm_gen = pgs->init(perm_gen_rs, pgs->init_size(), rem_set());
{- -------------------------------------------
(1)
---------------------------------------- -}
_g1_storage.initialize(g1_rs, 0);
_g1_committed = MemRegion((HeapWord*)_g1_storage.low(), (size_t) 0);
_g1_max_committed = _g1_committed;
_hrs = new HeapRegionSeq(_expansion_regions);
guarantee(_hrs != NULL, "Couldn't allocate HeapRegionSeq");
// 6843694 - ensure that the maximum region index can fit
// in the remembered set structures.
const size_t max_region_idx = ((size_t)1 << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1;
guarantee((max_regions() - 1) <= max_region_idx, "too many regions");
size_t max_cards_per_region = ((size_t)1 << (sizeof(CardIdx_t)*BitsPerByte-1)) - 1;
guarantee(HeapRegion::CardsPerRegion > 0, "make sure it's initialized");
guarantee((size_t) HeapRegion::CardsPerRegion < max_cards_per_region,
"too many cards per region");
HeapRegionSet::set_unrealistically_long_length(max_regions() + 1);
_bot_shared = new G1BlockOffsetSharedArray(_reserved,
heap_word_size(init_byte_size));
{- -------------------------------------------
(1)
---------------------------------------- -}
_g1h = this;
{- -------------------------------------------
(1)
---------------------------------------- -}
_in_cset_fast_test_length = max_regions();
_in_cset_fast_test_base = NEW_C_HEAP_ARRAY(bool, _in_cset_fast_test_length);
// We're biasing _in_cset_fast_test to avoid subtracting the
// beginning of the heap every time we want to index; basically
// it's the same with what we do with the card table.
_in_cset_fast_test = _in_cset_fast_test_base -
((size_t) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes);
// Clear the _cset_fast_test bitmap in anticipation of adding
// regions to the incremental collection set for the first
// evacuation pause.
clear_cset_fast_test();
// Create the ConcurrentMark data structure and thread.
// (Must do this late, so that "max_regions" is defined.)
_cm = new ConcurrentMark(heap_rs, (int) max_regions());
_cmThread = _cm->cmThread();
// Initialize the from_card cache structure of HeapRegionRemSet.
HeapRegionRemSet::init_heap(max_regions());
// Now expand into the initial heap size.
if (!expand(init_byte_size)) {
vm_exit_during_initialization("Failed to allocate initial heap.");
return JNI_ENOMEM;
}
// Perform any initialization actions delegated to the policy.
g1_policy()->init();
g1_policy()->note_start_of_mark_thread();
_refine_cte_cl =
new RefineCardTableEntryClosure(ConcurrentG1RefineThread::sts(),
g1_rem_set(),
concurrent_g1_refine());
JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl);
JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon,
SATB_Q_FL_lock,
G1SATBProcessCompletedThreshold,
Shared_SATB_Q_lock);
JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
DirtyCardQ_FL_lock,
concurrent_g1_refine()->yellow_zone(),
concurrent_g1_refine()->red_zone(),
Shared_DirtyCardQ_lock);
if (G1DeferredRSUpdate) {
dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
DirtyCardQ_FL_lock,
-1, // never trigger processing
-1, // no limit on length
Shared_DirtyCardQ_lock,
&JavaThread::dirty_card_queue_set());
}
// Initialize the card queue set used to hold cards containing
// references into the collection set.
_into_cset_dirty_card_queue_set.initialize(DirtyCardQ_CBL_mon,
DirtyCardQ_FL_lock,
-1, // never trigger processing
-1, // no limit on length
Shared_DirtyCardQ_lock,
&JavaThread::dirty_card_queue_set());
// In case we're keeping closure specialization stats, initialize those
// counts and that mechanism.
SpecializationStats::clear();
_gc_alloc_region_list = NULL;
// Do later initialization work for concurrent refinement.
_cg1r->init();
// Here we allocate the dummy full region that is required by the
// G1AllocRegion class. If we don't pass an address in the reserved
// space here, lots of asserts fire.
MemRegion mr(_g1_reserved.start(), HeapRegion::GrainWords);
HeapRegion* dummy_region = new HeapRegion(_bot_shared, mr, true);
// We'll re-use the same region whether the alloc region will
// require BOT updates or not and, if it doesn't, then a non-young
// region will complain that it cannot support allocations without
// BOT updates. So we'll tag the dummy region as young to avoid that.
dummy_region->set_young();
// Make sure it's full.
dummy_region->set_top(dummy_region->end());
G1AllocRegion::setup(this, dummy_region);
init_mutator_alloc_region();
// Do create of the monitoring and management support so that
// values in the heap have been properly initialized.
_g1mm = new G1MonitoringSupport(this, &_g1_storage);
{- -------------------------------------------
(1) リターン
---------------------------------------- -}
return JNI_OK;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.