G1收集器和ZGC收集器

2022-10-08 21:45:17 字數 3306 閱讀 8071

不要把垃圾收集器的功能看的太單一,除了**垃圾之外,記憶體的組織、分配、管理等操作也是垃圾收集器的工作。有的垃圾收集器選擇分代設計,有的選擇不分代。

垃圾收集器的效能主要從三方面考慮:停頓時間、吞吐量和記憶體占用

對於第二點,這三種目標無法同時滿足,乙個垃圾**器基本只能滿足其中的一到兩點。比如這篇筆記中介紹的g1和zgc都在記憶體占用方面頗高,而g1更加關注吞吐量,zgc更加關注停頓時間。

吞吐量即程式執行時間在總執行時間中所佔的比例,總執行時間=程式執行時間+垃圾**時間。

開始之前可以掃一眼之前的一篇文章:jvm 二 垃圾清理

貌似在jdk9到jdk17中預設的垃圾收集器都是g1。

g1收集器的特徵:

主要關注吞吐量,即滿足垃圾清理占用的時間在程式總執行時間中所佔的比例足夠小。

使用region作為記憶體管理的單元

分代,但使用mixed gc,即並非一次清理只面向某乙個分代

基於標記整理演算法,不會產生記憶體碎片

g1中的region都一樣大,可以使用-xx:g1heapregionsize設定,取值範圍為1~32mb

難免有大於最大region容量的大物件,只要乙個物件超過region容量的一半,g1就認為它是乙個大物件,存放大物件的區域稱作humongous區域,大物件存在於n個連續的humongous region區域中,g1對待它們的行為類似老年代。

g1會權衡**乙個region的收益,即可以獲得的空間和**所需的時間,然後參考使用者設定的-xx:maxgcpausemillis(最大gc暫停時間),**在該時間內可以完成那些的region中,**收益最大的那些。

雖然使用者可以設定乙個它期待的gc暫停時間,但這個值應該是合理的,不能異想天開。如果gc暫停時間設定的太小,會導致記憶體**的時間趕不上記憶體分配時間從而引發頻繁的fullgc

記憶集是為了解決標記過程中發現系統中存在的跨代引用,在傳統的新生代——老年代模型中,只有兩個分割槽,所以只需要維護乙個簡單的記憶集,而g1將記憶體區分為很多region,它的每乙個region都需要維護乙個自己的記憶集,所以它占用的記憶體也會較高。

初始標記:簡單的標記gc roots能直接關聯到的物件,必須停頓使用者執行緒,但時間很短。

併發標記:從初始標記得到的內容,對堆中物件進行掃瞄標記,該階段與使用者執行緒併發

最終標記:重新檢查並標記那些併發標記階段由於使用者操作而修改的引用關係

篩選**:**,選出指定停頓時間內**價值最高的那些region,複製其中的存活物件到新region,清理舊region。由於出現移動操作,需要停止使用者執行緒。

g1**器只有併發標記階段與使用者執行緒併發

g1收集器的優點在於它會收集那些成本最高的region,設定乙個期待的最大的停止時間。

對於當前系統,記憶體不再緊張,g1包括後面的zgc收集器為了獲得更短的停止時間都做了一些妥協,比如劃分region,一次不完成整個堆(新生代或老年代)的清理,只清理其中一部分。這種思想說成白話就是:如果當前記憶體空間不算緊張,那就一次清除少點兒,緩緩再清

也基於region,但是region是動態的。可以動態建立,具有動態大小,可以動態變化。

(暫時)不分代

使用染色指標

極低的停頓時間

小型region:2mb,防置小於256kb的物件

中型region:32mb,放置大於等於256kb,小於4mb的物件

大型region:容量不固定,可以動態變化,放置大於等於4mb的物件

簡單來說,就是現在的作業系統由於物理硬體大小限制,並沒有用上位址空間全部位,zgc使用這些空餘的位來儲存gc需要的額外資訊。

有些垃圾收集器把額外資訊放置在物件頭上,有些放在其它與物件不相關的資料結構中,如bitmap,zgc放在物件指標中沒被用到的位上,這樣不需要額外的空間。當然也有缺點,這導致了系統可用的定址空間變小,也就是系統可安裝的記憶體變小(4tb,目前來說是足夠使用還有不小的富餘,而且從目前的發展方向來看,大部分系統不再縱向擴充套件系統的效能)。

zgc和之前的一款並不在jdk中的垃圾收集器shenandoah都支援併發清除過程。

使用複製演算法舉例,在之前的垃圾收集器中,該操作必須停止使用者執行緒,這是因為使用者可能繼續讀寫因為本次無需被清除而被複製到其它位置的物件,此時對該物件的修改可能體會不到新物件上。

shenandoash使用brooks pointer技術解決這一問題(zgc應該也是),核心思想即**指標,即在物件前新增乙個新的引用字段,正常情況下該引用字段指向物件自己,當產生複製,該指標可以指向複製後的物件,然後任何對舊物件的訪問都可以直接**到新物件上。

問題就是物件訪問多了一層成本。

併發標記:從圖中可以看到,併發標記前後也需要停止使用者執行緒,和其它收集器一樣,進行初始標記和最終標記過程。

併發預備重分配:因為沒有類似記憶集的結構,所以zgc掃瞄所有region,決定清除哪些region,這些被清除的region會被放到重分配集中,被清除的region中的部分無需清除的內容後面需要複製到其它位置

併發重分配:執行複製,為每個重分配集中的region維護乙個**表,記錄從舊物件到新物件的轉換關係。當此時有使用者執行緒訪問了這些物件中的乙個,zgc會查詢**表,找到複製後的物件位址,並且在此次就把該物件的引用更新成新的,下次就不用再多一次的**了。

併發重對映:將之前的舊引用更新成新引用。

垃圾收集器(五) G1收集器

初始標記,標記gc roots直接關聯的物件,新增tams標記 兩個指標 stw 併發標記,從gc roots沿著引用關係查詢,如果使用者執行緒同時修改了引用關係,新增satb標記 此時的新物件分配到tams標記之外的區域 併發。最終標記 處理satb標記,stw 篩選 按照 價值進行 對於乙個re...

JVM垃圾收集器之CMS收集器

cms concurrent mark sweep 收集器是一種以獲取最短 停頓時間為目標的收集器。1 cms使用的演算法 cms使用的演算法為 標記 清除 演算法 2 執行過程4步驟 a 初始標記 cms initial mark b 併發標記 cms concurrent mark c 重新標記...

並行收集器

預設情況下伺服器上選擇並行收集器。1 並行收集器 這裡也稱為吞吐量收集器 是類似於序列收集器的分代收集器 主要區別在於多個執行緒用於加速垃圾收集。使用命令列選項啟用並行收集器 xx useparallelgc。2 可以使用命令列選項控制垃圾收集器執行緒的數量 xx parallelgcthreads...