Serial收集器
Serial收集器最早發(fā)展的,歷史最悠久的收集器,它是單線程的新生代收集器,在回收的時候會暫停所有用戶線程(Stop the world),使用復(fù)制算法。它是虛擬機在client模式下的默認垃圾收集器,它的特點:簡單而高效,因為它是單線程的,不像其他多線程收集器要處理線程交互的問題,可以專心做垃圾收集。
Serial Old收集器
它也是跟Serial收集器一樣,是單線程的,只是Serial收集器是對新生代進行回收,Serial Old是對老年代進行回收,Serial Old使用“標(biāo)記-整理”算法。
ParNew收集器
它是Serial收集器的多線程版本,除了使用多條線程外,其余行為包括Serial收集器的所有控制參數(shù)(如:-XX:SurvivorRatio
、-XX:PretenureSizeThreshold
、-XX:HandlePromotionFailure
等)、收集算法、Stop the world、對象分配規(guī)則、回收策略都與Serial收集器一樣。
Parallel Scavenge收集器
它跟ParNew收集器差不多,是多線程、使用復(fù)制算法的新生代收集器,不過它的關(guān)注點跟其他收集器不同,其他收集器希望能盡量縮短垃圾收集的停頓時間,而它希望提高垃圾收集的吞吐量。吞吐量 = 運行用戶代碼的時間 / (運行用戶代碼時間 + 垃圾回收時間),虛擬機總共運行了100分鐘,垃圾收集用了1分鐘,那它的吞吐量就是99%。縮短垃圾收集的停頓時間有利于用戶與程序的交互,而提高吞吐量可以更高效的利用CPU。
Parallel Scavenge收集器提供了兩個參數(shù)用來控制吞吐量,分別是控制垃圾收集最大停頓時間的-XX:MaxGCPauseMillis
和直接設(shè)置吞吐量大小的-XX:GCTimeRatio
。
MaxGCPauseMillis
是設(shè)置一個大于0的垃圾收集停頓時間,收集器在收集垃圾時盡量不超過該設(shè)定。這個參數(shù)也不是越低越好,停頓時間變低,可能會導(dǎo)致新生代空間變小(新生代空間小,回收時間少)或者吞吐量下降。GCTimeRatio
是設(shè)定一個值來控制垃圾收集時間占總時間的比率,比如99,吞吐量就是 1 / (1 + 99) = 1%。
Parallel Scavenge收集器還提供一個參數(shù),-XX:+useAdaptiveSizePolicy
,設(shè)定了這個參數(shù),就不需要手動指定新生代的大小(-Xmn
)、Eden和Survivor區(qū)的大小比例(-XX:SurvivorRatio
)、晉升老年代對象年齡(-XX:PretenureSizeThreshold
)等細節(jié)參數(shù),虛擬機會根據(jù)系統(tǒng)的運行情況和監(jiān)控信息,動態(tài)調(diào)整這些參數(shù)以獲得最短的垃圾收集停頓時間或者最高的吞吐量,這也是Parallel Scavenge收集器和ParNew收集器的一個重要區(qū)別之一。
Paralle Old收集器
它是Parallel Scavenge的老年代版本,在注重吞吐量和CPU使用效率的情況下,可以使用Paralle Scavenge和Parallel Old的組合。
CMS收集器
CMS(Concurrent Mark Sweep)收集器是旨在獲取最短回收停頓時間,一些與用戶交互性比較強的應(yīng)用就可以用此收集器。
它的垃圾回收分四個階段:
- 初始標(biāo)記
- 并發(fā)標(biāo)記
- 重新標(biāo)記
- 并發(fā)清除
初始標(biāo)記是找到那些GC Roots(虛擬機棧幀中的局部變量引用的對象、類的靜態(tài)變量引用的對象、常量池中的常量引用的對象、本地方法棧中JNI引用的對象);并發(fā)標(biāo)記就是一個GC Roots Tracing的過程;重新標(biāo)記是修正在并發(fā)標(biāo)記過程中因程序繼續(xù)運行而導(dǎo)致對象引用關(guān)系發(fā)生變化的情況;并發(fā)清除是多線程清除。
CMS收集器也有一些缺點:
- 由于CMS收集器回收垃圾的時候是與用戶線程同時運行的(大部分時間來說),本來CPU資源都用于用戶線程,現(xiàn)在垃圾回收線程占用了部分CPU資源,可能會導(dǎo)致程序速度下降。
- CMS收集器無法處理浮動垃圾。浮動垃圾,是在并發(fā)清理的過程中由于用戶線程繼續(xù)運行而新產(chǎn)生的垃圾,
- CMS收集器是使用“標(biāo)記-清除”算法的,因此會產(chǎn)生內(nèi)存碎片。當(dāng)沒有足夠大的連續(xù)空間時,會觸發(fā) FULL GC。
G1收集器
G1收集器是最新的一個垃圾收集器,從官網(wǎng)的介紹上看,如果機器核心數(shù)量多、內(nèi)存空間大,可以使用這個垃圾收集器,它可以充分利用硬件資源,縮短停頓時間。
G1收集器把堆劃分為多個region,有些是新生代region(多個新生代region不需要連續(xù),老年代也是如此),有些是老年代region,從整體上看,G1收集器使用的算法是“標(biāo)記-整理”,但從局部上看(region之間),使用的是“標(biāo)記-復(fù)制”算法。
G1收集器會根據(jù)之前的垃圾收集時間,建立可預(yù)測的停頓模型,它可以保證大多數(shù)情況下垃圾收集時間不超過指定的時間。G1收集器在后臺維護一個優(yōu)先列表,每次回收時,會根據(jù)允許的垃圾收集時間找出回收價值最大的region(垃圾對象多)。
在回收某些region的時候,有可能其他region的對象引用了該region的對象,因此要掃描全堆才能確定該region的垃圾對象。G1是這樣解決的(其他的分代垃圾收集器也是這樣處理老年代與新生代之間的互相引用問題),每個region對應(yīng)一個remembered set,里面記錄了哪些對象被其他region引用了。每次有Reference類型的數(shù)據(jù)更改時,虛擬機會檢查引用其他對象的對象和被引用的對象是否在同一個region,如果不是,則通過CardTable記錄相關(guān)信息到被引用對象的那個region的remembered set中。等到下次對該region GC時,虛擬機不用掃描其他的region,便知道有哪些對象被其他region的對象引用了。
G1收集器收集步驟大致分為:
- 初始標(biāo)記
- 并發(fā)標(biāo)記
- 最終標(biāo)記
- 篩選回收
初始標(biāo)記是標(biāo)記那些GC Roots能關(guān)聯(lián)到的對象;并發(fā)標(biāo)記是一個GC Roots Tracing的過程,對其他對象進行可達性分析,在這個過程中,對象之間的引用關(guān)系可能會發(fā)生變化,虛擬機把這些變化記錄在 remembered set logs中,最終標(biāo)記是修正那些變化,把remembered set logs中的記錄合并到remembered set中。
參考資料
《深入理解JAVA虛擬機》-周志明