@
G1采用標記-整理
初步介紹:
G1收集器主要有初始標記,並發標記,最終標記和篩選刪除四部分,G1收集器主要的特點就是它雖然理論上還有新生代和老年代概念,但是卻將內存分為若干個大小相等的region,會有一個優先回收列表,回收掉回收收益最大的那個region。
G1收集器是一款在server端運行的垃圾收集器,專門針對於擁有多核處理器和大內存的機器,在JDK 7u4版本發行時被正式推出,在JDK9中更被指定為官方GC收集器。它滿足高吞吐量的同時滿足GC停頓的時間盡可能短。
一些關鍵問題如何處理?
G1將堆內存“化整為零”的“解題思路”,一些問題如何處理:
跨Region引用對象?
問題1: 將Java堆分成多個獨立Region后,Region里面存在的跨Region引用對象如何解決?
使用記憶集避免全堆作為GC Roots掃描
這部分在分代收集和記憶集里有講
簡述分代收集理論:
根據弱,強分帶假說,設置新生代,老年代...根據跨帶引用假說在新生代上建立記憶集,記錄老年代哪些部分有引用, gc這部分即可.
簡述記憶集
記憶集是一種用於記錄從非收集區域指向收集區域的指針集合的抽象數據結構
記憶集記錄精讀
不考慮效率和成本,最簡單的實現可以用非收集區域中所有含跨代引用的對象數組..但空間開銷大,成本高.
在垃圾收集的場景中,收集器只需要通過記憶集判斷出某一塊非收集區域是否存在有指向了收集區域的指針,故選擇更粗狂的顆粒記錄,可供選擇的有 字節精讀,對象精讀,卡精讀(卡表).
·
卡精度:每個記錄精確到一塊內存區域,該區域內有對象含有跨代指針.
第三種“卡精度”所指的是用一種稱為“卡表”(Card Table)的方式去實現記憶集[
卡表就是記憶集的一種具體實現,它定義了記憶集的記錄精度、與堆內存的映射關系等。卡表最簡單的形式可以只是一個字節數組.
下圖是卡表作為字節數組的示意圖,
問題2: 並發標記階段如何保證收集線程與用戶線程互不干擾地運行?
這里首先要解決的是用戶線程改變對象引用關系時,必須保證其不能打破原本的對象圖結構,導致標記結果出現錯誤,
該問題的解決辦法筆者已經抽出獨立小節來講解過(見3.4.6節):CMS收集器采用增量更新算法實現,而G1收集器則是通過原始快照(SATB)算法來實現的
什么是原始快照?--見鏈接
原始快照的理解: 如果刪除黑色 指向白色的引用, 同上面, 也是先記下,回頭再gc掃描.
原始快照用來解決:可達性分析的"對象消失"問題.
原始快照要破壞的是第二個條件,當灰色對象要刪除指向白色對象的引用關系時,就將這個要刪
除的引用記錄下來,在並發掃描結束之后,再將這些記錄過的引用關系中的灰色對象為根,重新掃描
一次。這也可以簡化理解為,無論引用關系刪除與否,都會按照剛剛開始掃描那一刻的對象圖快照來
進行搜索。