深入理解JVM(③)低延遲的Shenandoah收集器


前言

Shenandoah作為第一款不由Oracle(包括一起的Sun)公司的虛擬機團隊所領導開發的HotSpot垃圾收集器。是只存在於OpenJDK當中的,最初由RedHat公司創建的,在2014年的時候貢獻給了OpenJDK。

與G1相比的優點

從代碼的歷史淵源上來看,Shenandoah收集器更像是G1的下一代繼承者,兩者相似的堆內存布局,在初始標記、並發標記等許多階段的處理思路都高度一致。
但是Shenandoah相比G1還是至少有三個明顯的不同之處。
1、支持並發的整理算法,G1的回收階段是可以多線程並行的,但卻不鞥呢與用戶線程並發。
2、Shenandoah是默認不使用分代收集的,不會有專門的新生代Region或者老年代Region的存在。
3、Shenandoah摒棄了在G1中耗費大量內存和計算資源去維護的記憶集,改用名為“連接矩陣”(Connection Matrix)的全局數據結果來記錄誇Region的引用關系降低了誇代維護的消耗。
Shenandoah收集器的跨代“連接矩陣”示意圖
Shenandoah收集器連接矩陣
連接矩陣可以簡單的理解為一張二維表格,如果Region N有對象指向Region M,就在表格的N行M列中打上一個標記,如上圖所示,如果Region 5中的對象Object C引用了Region 3 的Object B,Object B又引用了Region 1 的Object A,那么連接矩陣就中就會在5行3列、3行1列中打上標記。在回收時通過這張表格就可以得出哪些Region 之間產生了跨代引用。

收集過程

Shenandoah收集器的工作過程大致可以划分為以下九個階段:

  • 初始標記:與G1一樣,首先標記與GC Roots直接關聯的對象,這個階段仍是“Stop The World”的,但停頓時間與堆大小無關,至於GC Roots的數量相關。
  • 並發標記:與G1一樣,編輯對象圖,標記出全部可達的對象,與用戶線程一起並發,時間長短與堆中存活對象的數量以及對象圖的結構復雜程度有關。
  • 最終標記:與G1一樣,處理剩余的SATB掃描,並在這個階段統計出回收價值最高的Region,將這些Region構成一組回收集。此階段也會有一小段短暫的停頓。
  • 並發清理:這個階段用於清理那些整個區域內連一個存活對象都沒有找到的Region。
  • 並發回收:這個階段是Shenandoah與之前HotSpot中其他收集器的核心差異。在這個階段,Shenandoah要把回收集里面的存活對象先復制一份到其他未被使用的Region中。但是有個難點是在移動對象的同時,用戶線程仍然可能不停的對被移動的對象進行讀寫訪問,移動對象之后整個內存中所有指向該對象的引用都還是舊對象的地址,這是很難一瞬間全部改變過來的。對於這個難點,Shenandoah將會通過讀屏障和被稱為“Brooks Pointers”的轉發指針來解決
    並發回收階段運行時間的長短取決於回收集的大小。
  • 初始引用更新:並發回收階段復制對象結束后,還需要把堆中所有指向舊對象的引用修正蛋糕復制后的新地址,這個操作稱為引用更新。這個階段就是對這個操作進行初始化的,初始引用更新時間很短,會產生一個非常短暫的停頓。
  • 並發引用更新:真正開始進行引用更新操作,這個階段是與用戶線程一起並發的,時間長短取決於內存中涉及的引用數量的多少。
  • 最終引用更新:解決了堆中的引用更新后,還要修正存在於GC Roots 中的引用。這個階段是Shenandoah的最后一次停頓,時間長短與GC Roots的數量有關。
  • 並發清理:經過並發回收和引用更新之后,整個回收集中所有的Region已再無存活對象,最后再調用一次並發清理過程來回收這些Region 的內存空間,供以后新對象分配使用。

這九個階段的工作過程可能拆的比較瑣碎,只要抓住其中三個最重要的並發節點(並發標記、並發回收、並發引用更新)就好理解Shenandoah的運作過程了。


轉發指針(Brooks Pointer)

Shenandoah收集器的並發回收的核心是,轉發指針。
轉發指針的核心內容就是,在原有對象布局結構的最前面統一增加一個新的引用字段,在正常不處於並發移動的情況下,該引用指向對象自己。
如下圖:
在這里插入圖片描述
轉發指針加入后帶來的收益自然是當對象擁有了一份新的副本時,只需要修改一處指針的值,即舊對象上轉發指針的引用位置,使其指向新對象,便可將所有對該對象的訪問轉發到新的副本上。這樣只要對象的內存仍然存在,未被清理掉,虛擬機內存中所有通過舊引用地址訪問的代碼仍然可用,都會被自動轉發到新對象上繼續工作。
如下圖:
Brooks Pointers
Brooks Pointers 轉發指針在設計上決定了它是必然會出現多線程競爭問題的。Shenandoah收集器是通過比較交換(Compare And Swap,CAS)操作來保證並發時堆中的訪問正確性的。

總結

1、Shenandoah收集器保證了收集垃圾的低延遲。
2、但是使用了過多的寫屏障,所以導致Shenandoah收集器的弱項很明顯,當數據量大的時候會產生高運行負擔而使得吞吐量下降。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM