資深架構師的Java虛擬機學習 ------ 垃圾收集器

HotSpot JVM收集器java

上面有7中收集器,分爲兩塊,上面爲新生代收集器,下面是老年代收集器。若是兩個收集器之間存在連線,就說明它們能夠搭配使用。算法

Serial(串行GC)收集器多線程

Serial收集器是一個新生代收集器,單線程執行,使用複製算法。它在進行垃圾收集時,必須暫停其餘全部的工做線程(用戶線程)。是Jvm client模式下默認的新生代收集器。對於限定單個CPU的環境來講,Serial收集器因爲沒有線程交互的開銷,專心作垃圾收集天然能夠得到最高的單線程收集效率。併發

ParNew(並行GC)收集器oracle

ParNew收集器其實就是serial收集器的多線程版本,除了使用多條線程進行垃圾收集以外,其他行爲與Serial收集器同樣。性能

Parallel Scavenge(並行回收GC)收集器優化

Parallel Scavenge收集器也是一個新生代收集器,它也是使用複製算法的收集器,又是並行多線程收集器。parallel Scavenge收集器的特色是它的關注點與其餘收集器不一樣,CMS等收集器的關注點是儘量地縮短垃圾收集時用戶線程的停頓時間,而parallel Scavenge收集器的目標則是達到一個可控制的吞吐量。吞吐量= 程序運行時間/(程序運行時間 + 垃圾收集時間),虛擬機總共運行了100分鐘。其中垃圾收集花掉1分鐘,那吞吐量就是99%。線程

Serial Old(串行GC)收集器code

Serial Old是Serial收集器的老年代版本,它一樣使用一個單線程執行收集,使用「標記-整理」算法。主要使用在Client模式下的虛擬機。對象

Parallel Old(並行GC)收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多線程和「標記-整理」算法。

CMS(併發GC)收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間爲目標的收集器。

CMS收集器是基於「標記-清除」算法實現的,整個收集過程大體分爲4個步驟:

①.初始標記(CMS initial mark)

②.併發標記(CMS concurrenr mark)

③.從新標記(CMS remark)

④.併發清除(CMS concurrent sweep)

其中初始標記、從新標記這兩個步驟任然須要停頓其餘用戶線程。初始標記僅僅只是標記出GC ROOTS能直接關聯到的對象,速度很快,併發標記階段是進行GC ROOTS 根搜索算法階段,會斷定對象是否存活。而從新標記階段則是爲了修正併發標記期間,因用戶程序繼續運行而致使標記產生變更的那一部分對象的標記記錄,這個階段的停頓時間會被初始標記階段稍長,但比並發標記階段要短。

因爲整個過程當中耗時最長的併發標記和併發清除過程當中,收集器線程均可以與用戶線程一塊兒工做,因此總體來講,CMS收集器的內存回收過程是與用戶線程一塊兒併發執行的。

CMS收集器的優勢:併發收集、低停頓,可是CMS還遠遠達不到完美,主要有三個顯著缺點:

1,CMS收集器對CPU資源很是敏感。在併發階段,雖然不會致使用戶線程停頓,可是會佔用CPU資源而致使引用程序變慢,總吞吐量降低。CMS默認啓動的回收線程數是:(CPU數量+3) / 4。

2,CMS收集器沒法處理浮動垃圾,可能出現「Concurrent Mode Failure「,失敗後而致使另外一次Full GC的產生。因爲CMS併發清理階段用戶線程還在運行,伴隨程序的運行自熱會有新的垃圾不斷產生,這一部分垃圾出如今標記過程以後,CMS沒法在本次收集中處理它們,只好留待下一次GC時將其清理掉。這一部分垃圾稱爲「浮動垃圾」。也是因爲在垃圾收集階段用戶線程還須要運行,,即須要預留足夠的內存空間給用戶線程使用,所以CMS收集器不能像其餘收集器那樣等到老年代幾乎徹底被填滿了再進行收集,須要預留一部份內存空間提供併發收集時的程序運做使用。

在默認設置下,CMS收集器在老年代使用了68%的空間時就會被激活,也能夠經過參數-XX:CMSInitiatingOccupancyFraction的值來提供觸發百分比,以下降內存回收次數提升性能。要是CMS運行期間預留的內存沒法知足程序其餘線程須要,就會出現「Concurrent Mode Failure」失敗,這時候虛擬機將啓動後備預案:臨時啓用Serial Old收集器來從新進行老年代的垃圾收集,這樣停頓時間就很長了。

因此說參數-XX:CMSInitiatingOccupancyFraction設置的太高將會很容易致使「Concurrent Mode Failure」失敗,性能反而下降。

3,最後一個缺點,CMS是基於「標記-清除」算法實現的收集器,使用「標記-清除」算法收集後,會產生大量碎片。空間碎片太多時,將會給對象分配帶來不少麻煩,好比說大對象,內存空間找不到連續的空間來分配不得不提早觸發一次Full GC。爲了解決這個問題,CMS收集器提供了一個-XX:UseCMSCompactAtFullCollection開關參數,用於在Full GC以後增長一個碎片整理過程,還可經過-XX:CMSFullGCBeforeCompaction參數設置執行多少次不壓縮的Full GC以後,跟着來一次碎片整理過程。

G1收集器

G1(Garbage First)收集器是JDK1.7提供的一個新收集器,G1收集器基於「標記-整理」算法實現,也就是說不會產生內存碎片。還有一個特色以前的收集器進行收集的範圍都是整個新生代或老年代,而G1將整個Java堆(包括新生代,老年代)。

垃圾收集器參數總結:

 
-XX:+<option> 啓用選項 -XX:-<option> 不啓用選項 -XX:<option>=<number> -XX:<option>=<string>
 
參數 描述 -XX:+UseSerialGC Jvm運行在Client模式下的默認值,打開此開關後,使用Serial + Serial Old的收集器組合進行內存回收 -XX:+UseParNewGC 打開此開關後,使用ParNew + Serial Old的收集器進行垃圾回收 -XX:+UseConcMarkSweepGC 使用ParNew + CMS + Serial Old的收集器組合進行內存回收,Serial Old做爲CMS出現「Concurrent Mode Failure」失敗後的後備收集器使用。 -XX:+UseParallelGC Jvm運行在Server模式下的默認值,打開此開關後,使用Parallel Scavenge + Serial Old的收集器組合進行回收 -XX:+UseParallelOldGC 使用Parallel Scavenge + Parallel Old的收集器組合進行回收 -XX:SurvivorRatio 新生代中Eden區域與Survivor區域的容量比值,默認爲8,表明Eden:Subrvivor = 8:1 -XX:PretenureSizeThreshold 直接晉升到老年代對象的大小,設置這個參數後,大於這個參數的對象將直接在老年代分配 -XX:MaxTenuringThreshold 晉升到老年代的對象年齡,每次Minor GC以後,年齡就加1,當超過這個參數的值時進入老年代 -XX:UseAdaptiveSizePolicy 動態調整java堆中各個區域的大小以及進入老年代的年齡 -XX:+HandlePromotionFailure 是否容許新生代收集擔保,進行一次minor gc後, 另外一塊Survivor空間不足時,將直接會在老年代中保留 -XX:ParallelGCThreads 設置並行GC進行內存回收的線程數 -XX:GCTimeRatio GC時間佔總時間的比列,默認值爲99,即容許1%的GC時間,僅在使用Parallel Scavenge 收集器時有效 -XX:MaxGCPauseMillis 設置GC的最大停頓時間,在Parallel Scavenge 收集器下有效 -XX:CMSInitiatingOccupancyFraction 設置CMS收集器在老年代空間被使用多少後出發垃圾收集,默認值爲68%,僅在CMS收集器時有效,-XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSCompactAtFullCollection 因爲CMS收集器會產生碎片,此參數設置在垃圾收集器後是否須要一次內存碎片整理過程,僅在CMS收集器時有效 -XX:+CMSFullGCBeforeCompaction 設置CMS收集器在進行若干次垃圾收集後再進行一次內存碎片整理過程,一般與UseCMSCompactAtFullCollection參數一塊兒使用 -XX:+UseFastAccessorMethods 原始類型優化 -XX:+DisableExplicitGC 是否關閉手動System.gc -XX:+CMSParallelRemarkEnabled 下降標記停頓 -XX:LargePageSizeInBytes 內存頁的大小不可設置過大,會影響Perm的大小,-XX:LargePageSizeInBytes=128m

Client、Server模式默認GC

 
新生代GC方式 老年代和持久代GC方式

Client

Serial 串行GC Serial Old 串行GC
Server Parallel Scavenge 並行回收GC Parallel Old 並行GC

Sun/oracle JDK GC組合方式

 
新生代GC方式 老年代和持久代GC方式

-XX:+UseSerialGC

Serial 串行GC

Serial Old 串行GC

-XX:+UseParallelGC

Parallel Scavenge 並行回收GC

Serial Old 並行GC

-XX:+UseConcMarkSweepGC

ParNew 並行GC

CMS 併發GC

當出現「Concurrent Mode Failure」時

採用Serial Old 串行GC

-XX:+UseParNewGC

ParNew 並行GC

Serial Old 串行GC

-XX:+UseParallelOldGC

Parallel Scavenge 並行回收GC

Parallel Old 並行GC

-XX:+UseConcMarkSweepGC

-XX:+UseParNewGC

Serial 串行GC

CMS 併發GC

當出現「Concurrent Mode Failure」時

採用Serial Old 串行GC

相關文章
相關標籤/搜索