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

前言

Shenandoah做爲第一款不禁Oracle(包括一塊兒的Sun)公司的虛擬機團隊所領導開發的HotSpot垃圾收集器。是隻存在於OpenJDK當中的,最初由RedHat公司建立的,在2014年的時候貢獻給了OpenJDK。算法

與G1相比的優勢

從代碼的歷史淵源上來看,Shenandoah收集器更像是G1的下一代繼承者,二者類似的堆內存佈局,在初始標記、併發標記等許多階段的處理思路都高度一致。
可是Shenandoah相比G1仍是至少有三個明顯的不一樣之處。
一、支持併發的整理算法,G1的回收階段是能夠多線程並行的,但卻不鞥呢與用戶線程併發。
二、Shenandoah是默認不使用分代收集的,不會有專門的新生代Region或者老年代Region的存在。
三、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)操做來保證併發時堆中的訪問正確性的。線程

總結

一、Shenandoah收集器保證了收集垃圾的低延遲。
二、可是使用了過多的寫屏障,因此致使Shenandoah收集器的弱項很明顯,當數據量大的時候會產生高運行負擔而使得吞吐量降低。設計

相關文章
相關標籤/搜索