Shenandoah做爲第一款不禁Oracle(包括一塊兒的Sun)公司的虛擬機團隊所領導開發的HotSpot垃圾收集器。是隻存在於OpenJDK當中的,最初由RedHat公司建立的,在2014年的時候貢獻給了OpenJDK。算法
從代碼的歷史淵源上來看,Shenandoah收集器更像是G1的下一代繼承者,二者類似的堆內存佈局,在初始標記、併發標記等許多階段的處理思路都高度一致。
可是Shenandoah相比G1仍是至少有三個明顯的不一樣之處。
一、支持併發的整理算法,G1的回收階段是能夠多線程並行的,但卻不鞥呢與用戶線程併發。
二、Shenandoah是默認不使用分代收集的,不會有專門的新生代Region或者老年代Region的存在。
三、Shenandoah摒棄了在G1中耗費大量內存和計算資源去維護的記憶集,改用名爲「鏈接矩陣」(Connection Matrix)的全局數據結果來記錄誇Region的引用關係下降了誇代維護的消耗。
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收集器的工做過程大體能夠劃分爲如下九個階段:併發
這九個階段的工做過程可能拆的比較瑣碎,只要抓住其中三個最重要的併發節點(併發標記、併發回收、併發引用更新)就好理解Shenandoah的運做過程了。佈局
Shenandoah收集器的併發回收的核心是,轉發指針。
轉發指針的核心內容就是,在原有對象佈局結構的最前面統一增長一個新的引用字段,在正常不處於併發移動的狀況下,該引用指向對象本身。
以下圖:
轉發指針加入後帶來的收益天然是當對象擁有了一份新的副本時,只須要修改一處指針的值,即舊對象上轉發指針的引用位置,使其指向新對象,即可將全部對該對象的訪問轉發到新的副本上。這樣只要對象的內存仍然存在,未被清理掉,虛擬機內存中全部經過舊引用地址訪問的代碼仍然可用,都會被自動轉發到新對象上繼續工做。
以下圖:
Brooks Pointers 轉發指針在設計上決定了它是必然會出現多線程競爭問題的。Shenandoah收集器是經過比較交換(Compare And Swap,CAS)操做來保證併發時堆中的訪問正確性的。線程
一、Shenandoah收集器保證了收集垃圾的低延遲。
二、可是使用了過多的寫屏障,因此致使Shenandoah收集器的弱項很明顯,當數據量大的時候會產生高運行負擔而使得吞吐量降低。設計