我知道YGC花費的時間與伊甸園中的活物的數量成正比。我也明白,在主要集合(線程堆棧和靜態對象中的所有對象以及從這些對象可及的對象到達的所有對象)中如何計算活動對象。)如何在年輕一代的收藏中發現活的物體?
但我不明白活動對象是如何計算出來的年輕一代收藏? 如果它解析線程堆棧,那麼它需要解析伊甸園+終身空間,這不是我想象的情況。那麼JVM如何在伊甸園中找到活物並將它們複製到To Survivor
的空間中呢?
我知道YGC花費的時間與伊甸園中的活物的數量成正比。我也明白,在主要集合(線程堆棧和靜態對象中的所有對象以及從這些對象可及的對象到達的所有對象)中如何計算活動對象。)如何在年輕一代的收藏中發現活的物體?
但我不明白活動對象是如何計算出來的年輕一代收藏? 如果它解析線程堆棧,那麼它需要解析伊甸園+終身空間,這不是我想象的情況。那麼JVM如何在伊甸園中找到活物並將它們複製到To Survivor
的空間中呢?
在年輕一代的收藏中,活體是如何形成的?
的集合如何在代的HotSpot實現好高層次的描述可以在this article被發現。
一般而言,代收集標誌着年輕一代如下(假設我們只需要兩代人):
在HotSpot中,使用「卡片表」識別包含年輕代引用的舊一代對象。舊一代分爲512個字節的區域,每個區域都有一個「卡」。如果該區域包含任何舊的 - >新一代指針,則卡片中的一位被設置。在設置了卡位的區域中的對象隨後在新一代收集期間被追蹤。
棘手的事情是維護卡表,因爲新的空間參考被寫入舊的生成對象。在HotSpot中,這是通過使用軟件寫入屏障來實現的,只要將新的空間參考寫入對應於該卡的存儲區域中,該軟件寫入屏障便設置適當的卡的髒位。正如鏈接文章所指出的那樣,這使得在對象中設置參考字段更加昂貴,但顯然值得這樣做,因爲大部分時間只能收集新一代的時間節省了時間。
我在這裏引用article by Brian Goetz的相關文字。直到所有的活動對象已經 訪問
跟蹤垃圾收集器,如 複製,標記 - 清除和標記緊湊, 都是從根集開始掃描,對象之間 穿越參考, 。世代追蹤 收集器從根集 開始,但不遍歷 會導致生成較舊的 中的對象的引用,這會減少要跟蹤的對象圖的大小。
爲了追蹤最年輕的一代,垃圾收集器掃描相同的根集(堆棧和寄存器),並且還要掃描自上一代年輕代以來修改過的所有較舊(未收集)的一代。只有那些經過修改的對象纔有可能指向年輕一代的對象,因爲未修改的對象不可能指向最後修改後創建的對象。
所以棘手的部分是,GC如何知道自上次GC後修改了哪些對象?有許多可以使用的技術,但他們基本上都是爲了跟蹤對舊一代對象的寫入。這可以通過捕獲寫入(寫入障礙)或只是跟蹤所有寫入目標(寫入緩衝區,卡片標記)來完成,所有這些都會在GC未運行時增加程序執行的開銷(因此它不會顯示爲GC暫停時間,但在總時間內顯示)。如果可用,硬件支持會有很大幫助。只要每一個修改過的舊世代對象被掃描(掃描未修改的對象是浪費時間,但不會損害任何東西),追蹤不一定是確切的。
不錯的鏈接,謝謝。 – gkuzmin 2013-10-13 18:49:55
有些技術更正:卡表無條件地更新*,無論新指針是指新一代。基本上,語義是*髒標誌*。另外,即使卡表中的條目是全字節,它也只包含一位信息。這是爲了表現。 – 2014-02-01 13:33:29
確實! http://psy-lob-saw.blogspot.com.au/2014/10/the-jvm-write-barrier-card-marking.html – 2015-02-27 07:55:58