天天看點

JVM 源碼分析13 跨代引用cardTable && System.gc

  思考一個問題,在進行YGC時,如果young generation的Y對象被old generation中O對象引用,那麼稱O對象存在跨代引用,而且Y對象應該在本次垃圾回收中存活下來,是以old generation的對象在YGC時也是Strong root的一部分,如果每次YGC都去掃描old generation中所有對象的話,肯定會非常耗時,那麼有什麼好的解決方案呢?

如果隻掃描那些有young generation對象引用的對象,是不是效率可以達到最高,不過使用這種方式,需要有一個地方儲存這些對象的引用,是一個不小的記憶體開銷,是以Hotspot實作中,并沒采用這樣方式,而是使用一個GenRemSet資料結構,記錄包含這些對象的記憶體區域是clean or dirty狀态。

JVM 源碼分析13 跨代引用cardTable && System.gc

CardTable

CardTable是GenRemSet的一種實作,類似于一個數組,每個元素對應着堆記憶體的一塊區域是否存在跨代引用的對象,如果存在,該Card為dirty狀态。

GenRemSet随着堆記憶體一起初始化,通過具體的垃圾收集政策進行建立,比如CMS和G1是不一樣的,其中CMS對應的是CardTable。

如果目前的Card不是clean_card狀态,說明該Card對應的記憶體區域至少有一個對象引用着young generation的對象

如果拷貝之後的對象還在young generation,則執行

inline_write_ref_field_gc

重新把對應的Card設定為dirty。

每次的動作是先清除Card的dirty狀态,對象拷貝完成再判斷是否要設定為dirty,即非clean

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

JVM 源碼分析13 跨代引用cardTable && System.gc
JVM 源碼分析13 跨代引用cardTable && System.gc

堆實作和回收算法對應關系:

1、UseParallelGC:ParallelScavengeHeap

2、UseG1GC:G1CollectedHeap

3、預設或者CMS:GenCollectedHeap