詳解 ZGC
ZGC 特點
ZGC 是最新的 JDK1.11 版本中提供的高效垃圾回收算法,ZGC 針對大堆內存設計可以支持 TB 級別的堆,ZGC 非常高效,能夠做到 10ms 以下的回收停頓時間。
這麼快的響應,ZGC 是如何做到的呢?這是由於 ZGC 具有以下特點。
-
ZGC 使用了着色指針技術,我們知道 64 位平臺上,一個指針的可用位是 64 位,ZGC 限制最大支持 4TB 的堆,這樣尋址只需要使用 42 位,那麼剩下 22 位就可以用來保存額外的信息,着色指針技術就是利用指針的額外信息位,在指針上對對象做着色標記。
-
第二個特點是使用讀屏障,ZGC 使用讀屏障來解決 GC 線程和應用線程可能併發修改對象狀態的問題,而不是簡單粗暴的通過 STW 來進行全局的鎖定。使用讀屏障只會在單個對象的處理上有概率被減速。
-
由於讀屏障的作用,進行垃圾回收的大部分時候都是不需要 STW 的,因此 ZGC 的大部分時間都是併發處理,也就是 ZGC 的第三個特點。
-
第四個特點是基於 Region,這與 G1 算法一樣,不過雖然也分了 Region,但是並沒有進行分代。ZGC 的 Region 不像 G1 那樣是固定大小,而是動態地決定 Region 的大小,Region 可以動態創建和銷燬。這樣可以更好的對大對象進行分配管理。
-
第五個特點是壓縮整理。CMS 算法清理對象時原地回收,會存在內存碎片問題。ZGC 和 G1 一樣,也會在回收後對 Region 中的對象進行移動合併,解決了碎片問題。
雖然 ZGC 的大部分時間是併發進行的,但是還會有短暫的停頓。來看一下 ZGC 的回收過程。
ZGC 回收過程
如下圖所示,使用 ZGC 算法進行回收,從上往下看。初始狀態時,整個堆空間被劃分爲大小不等的許多 Region,即圖中綠色的方塊。
開始進行回收時,ZGC 首先會進行一個短暫的 STW,來進行 roots 標記。這個步驟非常短,因爲 roots 的總數通常比較小。
然後就開始進行併發標記,如上圖所示,通過對對象指針進行着色來進行標記,結合讀屏障解決單個對象的併發問題。其實,這個階段在最後還是會有一個非常短的 STW 停頓,用來處理一些邊緣情況,這個階段絕大部分時間是併發進行的,所以沒有明顯標出這個停頓。
下一個是清理階段,這個階段會把標記爲不在使用的對象進行回收,如上圖所示,把橘色的不在使用的對象進行了回收。
最後一個階段是重定位,重定位就是對 GC 後存活的對象進行移動,來釋放大塊的內存空間,解決碎片問題。
重定位最開始會有一個短暫的 STW,用來重定位集合中的 root 對象。暫停時間取決於 root 的數量、重定位集與對象的總活動集的比率。
最後是併發重定位,這個過程也是通過讀屏障,與應用線程併發進行的。