jvm垃圾收集器你學廢了嗎(二)

前言

前面一篇文章講了6種垃圾收集器分別是Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS(傳送門
今天我們來說一下G1(Garbage First)收集器,爲什麼把G1收集器單獨拿出來說呢?它是垃圾收集器技術發展歷史上的里程碑式的成果,下面我們細細道來
在這裏插入圖片描述

G1收集器

G1收集器開創了收集器面向局部手機的設計思路和基於Region的內存佈局形式,G1也是遵循分代收集理論的,但是它的內存佈局有以下幾點變化

  • G1不再使用固定大小以及固定數量的分代區域劃分,而是把連續的java堆劃分爲多個大小相等的獨立區域(Region),
  • 每個Region區域可根據需要扮演新生代和老年代
  • 收集器還能對不同角色的Region進行不同的策略處理
  • 如果大小超過Region的一半就認爲是大對象

在這裏插入圖片描述

核心思想

G1收集器的核心思想就是,去追蹤各個Region的價值(這裏的價值就是指回收這塊Region區可以回收多大的內存空間),在後臺維護一個優先級表,然後按照用戶設置的收集停頓時間去按優先級表一次回收,保證了G1收集器在有限的時間內獲取儘可能高的收集效率

運作過程

G1的收集過程分爲四個步驟:

  • 初始標記
    標記GC Roots能直接關聯到的對象,並且修改TAMS指正的值,這個階段需要停頓,但是時間很短
    TAMS指針是什麼呢?G1收集器爲每個Region設計兩個TAMS指針,把一部分的Region區域劃分出來,用戶併發垃圾收集過程中用戶線程分配新對象
  • 併發標記
    對堆中的內向進行可達性分析,遞歸的掃描整個對象圖,並找出要回收的對象,這個階段耗時很長,但是可以和用戶線程併發執行
  • 最終標記
    在併發標記階段,難免會有用戶線程打破了原來的對象圖結構,解決這個問題問題的方案就是原始快照,最終標記就是對原始快照進行標記,這個階段也是需要短暫的暫停
  • 篩選回收
    對各個Region的回收價值和成本進行排序,根據用戶所期望的停頓時間,選擇性價比最高的Region區域進行回收。先講Region存活的對象移動到新的Region區域中,然後對舊Region進行回收,這個階段要進行對象的移動,所以必須要暫停用戶線程。

3個核心問題

  • 既然G1將java堆分成了多個Region,那Region裏存在這跨Region引用對象,G1是怎樣解決的呢
    記憶集,每個Region區域會維護自己的記憶集,記憶集會記錄下別的Region指向自己的指針,並標記這些指針分別在那些卡頁中,G1的記憶集是一個鍵值的結構,key是別的Region的起始地址,value是一個集合,裏面存放着卡表的索引號
  • 如果保證在併發標記階段垃圾收集縣線程和用戶線程互不干擾
    原始快照,原始快照記錄了那些對象的引用要被刪除了,等併發標記完成之後,在重新掃描一下這些元素,
  • 如何建立可靠的停頓預測模式?
    用戶可以通過-XX:MaxGCPauseMillis參數設置垃圾收集器的停頓時間,那如何來保證用戶的期望呢,G1會記錄每個Region的回收耗時和髒卡數量等,通過一系列的值來分析出平均狀態,這裏會提到一個衰減平均值,這是什麼意思呢,衰減平均值跟準確的代表 最近的 平均狀態,所以說G1根據這值來保證用戶的停頓時間。

優點

  • G1從整體上看使用的是標記-整理算法,從局部上看使用的是標記-複製算法,所以不會產生內存碎片
  • 打破了原來的分代思想
  • 按Region的收益動態的確定回收集

缺點

  • 每個Region無論是新生代還是老年代,都是維護一個自己的卡表,這導致G1的記憶集佔很大的堆空間

總結

G1收集器真的是很經典的收集器,也是JDK9默認的收集器,他的運行機制要比之前說到的複雜的多,看到這裏你學廢了嗎?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章