垃圾收集器算法
Throughtput收集器是一款關注吞吐量的收集器。這個收集器也是惟一一個實現了UseAdaptiveSizePolicy策略的垃圾收集器。容許用戶經過指定最大的暫停時間和垃圾收集器所佔用的時間百分比,而後動態調整JVM的參數來達到配置的目標。多線程
上圖是一個經典的垃圾收集器的圖,圖中有顏色的就是 throughput垃圾回收器 ,各個線表明的是各個垃圾回收器之間哪兩個能夠配合使用。併發
從上圖能夠看出 Parralel Scanvenge垃圾回收器不能和CMS配合使用。框架
ParallelScavenge收集器是新生代收集器,使用的是Scavenge GC。是一個並行收集器。在copping階段能夠多個線程一塊兒執行,在多線程的場景下可一儘可能的提升Minor GC的效率。目的是能夠達到一個可控的吞吐量。 性能
吞吐量 = 運行用戶代碼的時間/(運行用戶代碼時間+垃圾收集時間)測試 |
虛擬機運行總時間100分鐘,其中垃圾收集器運行了1分鐘,則吞吐量就是99%spa
ParallelScavenge收集器的來歷爲,在HotSpot VM開發的時候都是在分代式框架下開發,而且但願第三方開發者也能在這個框架下開發自定義的收集器,這樣就能和其餘收集器配合使用。可是有個開發者不肯意使用這個框架,而且憑藉本身的能力開發了並行收集器,這時候JVM中的並行收集器是不存在的。通過測試,這個收集器的性能仍是很是不錯的,因而就被放入到了HotSopt中成爲了ParallelScavenge收集器。這就是爲何這個收集器不能和CMS配合使用,由於它就不是在分代式框架下開發的。線程
ParallelScavenge是在jdk1.7以前的默認垃圾回收器。使用ParallelScavence收集器須要須要關注如下兩個參數:設計
這個參數控制GC最大的停頓時間。設置之後經過動態調整新生代的大小來達到暫停時間是能夠控制的。可是這個值不是越小越好。由於這個若是這個值設置的比較小,那一定會致使新生代的比較小,新生代空間比較小的話,會致使更加頻繁的minor GC,這樣總間隔時間就會變大。日誌
收集器運行時間所佔時間的比率,介於0到100的整數。
經過調整這兩個參數的大小能起到動態調整吞吐量和暫停時間的目的,這樣用戶不用關心新老年代應該各自設置多大,只須要設置好這兩個值,剩下的交給虛擬機動態調整。
Parallel Old是ParallelScavenge的老年代版本,以前若是新生代使用ParallelScavenge,老年代只能使用Serial Old,爲了彌補這個缺失,因此在jdk 1.6的時候開發了Parallel Old 老年代並行垃圾回收器,配合ParallelScavenge使用。此時二者雙劍合璧,才更能顯現出來Throughtput的強悍之處
單線程老年代收集器,主要用在client模式下,不過也做爲CMS垃圾收集器併發模式失效之後備用收集器。
Throughtput收集器配置
Throughtput收集器經過第一節的圖中能夠看出有兩種配置
-XX:+UseParallelGC
或者
-XX:+UseParallelOldGC
,這兩個配置任選一個,就會選中ParallelScavenge+Parallel Old組合做爲收集器。
打印的GC日誌以下
[Full GC (System.gc()) [PSYoungGen: 992K->0K(29696K)] [ParOldGen: 8K->761K(68608K)] 1000K->761K(98304K), [Metaspace: 3152K->3152K(1056768K)], 0.0060131 secs] [Times: user=0.02 sys=0.00, real=0.00 secs]
若是非得強制使用單線程老年代收集器(Serial Old)能夠以下配置:
-XX:+UseParallelGC -XX:-UserParallelOldGC
發生GC時,打印的日誌以下
[Full GC (System.gc()) [PSYoungGen: 928K->0K(29696K)] [PSOldGen: 8K->767K(68608K)] 936K->767K(98304K), [Metaspace: 3167K->3167K(1056768K)], 0.0023446 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
ParallelScavenge和ParNew
在收集器的圖中,咱們看到還有一個ParNew的新生代收集器,因爲CMS收集器不能配合ParallelScavenge使用,因此只剩下一個單線程的Serial收集器,爲了可以有所匹配,因此出來了並行的新生代收集器,它和ParallelScavenge相比有以下不一樣:
若是是關注吞吐量的應用,採用Throughput收集器是個不錯的選擇。而且能夠經過設置
-XX:ParallelGCThreads=N 來設置並行GC線程數。在使用的過程當中最好不要手工的指定新生代和老年代的大小,而是指定MaxGCPauseMills 和GCTimeRatio讓其自動調整,以達到最優值。同時設置咱們堆大小便可。
CMS收集器設計的初衷是了消除Throughtput收集器和Serial收集器FullGC週期的長時間停頓。CMD收集器在Minor GC時會暫停全部應用線程,而且以多線程的方式進行垃圾回收。
CMS收集器在FullGC時再也不暫停應用線程,而是使用若干個後臺線程按期的對老年代空間進行掃描,及時會後其中再也不使用的對象。這種作法使得CMS成爲一個低延遲的收集器。應用線程只在Minor GC以及後臺線程騷烤老年代時發生極其短暫的停頓。應用程序線程停頓的總時長與使用Throughtput收集器比起來短的多。
可是會付出額外的代價,那就是更高的CPU使用:必須有足夠的CPU資源用於後臺運行垃圾收集線程。除此以外,後臺再也不進行壓縮整理工做,也就是說堆回逐漸的碎片化。若是CMS的後臺線程沒法得到完成他們任務所須要的CPU資源,或者若是堆變的過分碎片化以致於沒法找到連續內存分配先對象,CMS就會蛻化爲Serial收集器的行爲,暫停全部應用線程,使用單線程進行回收,整理老年代空間,以後又恢復到併發運行,再次啓動後臺線程,直到堆變的再次過分碎片化。
開啓標誌:
-XX:+UseConcMarkSweepGC ,-XX:+UseParNewGC
這兩個標誌能夠開啓CMS垃圾回收器。