素小暖講JVM:HotSpot VM GC 的種類

本系列是用來記錄《深刻理解Java虛擬機》這本書的讀書筆記。方便本身查看,也方便你們查閱。java

欲速則不達,欲達則欲速!服務器

1、collector種類多線程

GC在 HotSpot VM 5.0裏有四種:併發

incremental (sometimes called train) low pause collector已被廢棄,不在介紹app

類別 serial collector parallel collector
throughput collector )
concurrent collector
(concurrent low pause collector)
介紹

單線程收集器性能

使用單線程去完成全部的GC工做,沒有線程間的通訊,這種方式會相對高效spa

並行收集器線程

使用多線程的方式,利用CUP來提升GC的效率,主要以到達必定的吞吐量爲目標code

併發收集器orm

使用多線程的方式,利用多CPU來提升GC的效率,併發完成大部分工做,使得GC pause短

試用場景 單處理器機器且沒有pause time的要求

適用於科學技術和後臺處理有中大規模數據集的應用

且運行在多處理器上,關注吞吐量(throughput)

適合中規模/大規模數據集大小的應用,應用服務器,電信領域。關注response time,而不是throughput
使用 Client模式下默認
可以使用
可用-XX:+UseSerialGC強制使用
優勢:對server應用沒什麼優勢
缺點:慢,不能充分發揮硬件資源

Server模式下默認

--YGC:PS FGC:Parallel MSC

可用-XX:+UseParallelGC

或-XX:+UseParallelOldGC強制指定

--ParallelGC表明FGC爲Parallel MSC

--ParallelOldGC表明FGC爲Parallel Compacting

優勢:高效

缺點:當heap變大後,形成的暫停時間會變得比較長

可用-XX:+UseConcMarkSweepGC強制指定

優勢:
對old進行回收時,對應用形成的暫停時間很是短,適合對延遲要求比較高的應用

缺點:
1.內存碎片和浮動垃圾
2.old去的內存分配效率低
3.回收的整個耗時比較長
4.和應用爭搶CPU

內存回收觸發

YGC
eden空間不足
FGC
old空間不足
perm空間不足
顯示調用System.gc() ,

包括RMI等的定時觸發

YGC
eden空間不足
FGC
old空間不足
perm空間不足
顯示調用System.gc() ,包括RMI等的定時觸發

YGC
eden空間不足
CMS GC
1.old Gen的使用率大的必定的比率 默認爲92%
2.配置了CMSClassUnloadingEnabled,且Perm Gen的使用達到必定的比率 默認爲92%
3.Hotspot本身根據估計決定是否要觸法
4.在配置了ExplictGCInvokesConcurrent的狀況下顯示

調用了System.gc.
Full GC(Serial MSC)
promotion failed 或 concurrent Mode Failure時;

內存回收觸發

時發生了什麼

YGC
清空eden+from中全部no ref的對象佔用的內存
將eden+from中的全部存活的對象copy到to中
在這個過程當中一些對象將晉升到old中:
--to放不下的
--存活次數超過tenuring threshold的
從新計算Tenuring Threshold;
單線程作以上動做
全程暫停應用
FGC
若是配置了CollectGen0First,則先觸發YGC
清空heap中no ref的對象,permgen中已經被卸載的classloader

中加載的class的信息
單線程作以上動做
全程暫停應用

YGC
同serial動做基本相同,不一樣點:
1.多線程處理
2.YGC的最後不只從新計算Tenuring Threshold,還會從新調整Eden和From的大小
FGC
1.如配置了ScavengeBeforeFullGC(默認),則先觸發YGC(??)
2.MSC:清空heap中的no ref對象,permgen中已經被卸載的classloader中加載的

class信息,並進行壓縮
3.Compacting:清空heap中部分no ref的對象,permgen中已經被卸載的classloader中加載的

class信息,並進行部分壓縮
多線程作以上動做.

YGC
同serial動做基本相同,不一樣點:
1.多線程處理
CMSGC:
1.old gen到達比率時只清除old gen中no ref的對象所佔用的空間
2.perm gen到達比率時只清除已被清除的classloader

加載的class信息
FGC
同serial

細節參數 可用-XX:+UseSerialGC強制使用
-XX:SurvivorRatio=x,控制eden/s0/s1的大小
-XX:MaxTenuringThreshold,用於控制對象在新生代存活的最大次數
-XX:PretenureSizeThreshold=x,控制超過多大的字節的對象就在old分配.
-XX:SurvivorRatio=x,控制eden/s0/s1的大小
-XX:MaxTenuringThreshold,用於控制對象在新生代存活的最大次數

-XX:UseAdaptiveSizePolicy 去掉YGC後動態調整eden from已經tenuringthreshold的動做

-XX:ParallelGCThreads 設置並行的線程數

XX:CMSInitiatingOccupancyFraction 設置old gen使用到達多少比率時觸發
-XX:CMSInitiatingPermOccupancyFraction,設置Perm Gen使用到達多少比率時觸發
-XX:+UseCMSInitiatingOccupancyOnly禁止hostspot自行觸發CMS GC

注:

  • throughput collector與concurrent low pause collector的區別是throughput collector只在young area使用使用多線程,而concurrent low pause collector則在tenured generation也使用多線程。
  • 根據官方文檔,他們倆個須要在多CPU的狀況下,才能發揮做用。在一個CPU的狀況下,會不如默認的serial collector,由於線程管理須要耗費CPU資源。而在兩個CPU的狀況下,也提升不大。只是在更多CPU的狀況下,纔會有所提升。固然 concurrent low pause collector有一種模式能夠在CPU較少的機器上,提供儘量少的停頓的模式,見CMS GC Incremental mode
  • 當要使用throughput collector時,在java opt里加上-XX:+UseParallelGC,啓動throughput collector收集。也可加上-XX:ParallelGCThreads=<desired number>來改變線程數。還有兩個參數 -XX:MaxGCPauseMillis=<nnn>和 -XX:GCTimeRatio=<nnn>,MaxGCPauseMillis=<nnn>用來控制最大暫停時間,而-XX: GCTimeRatio能夠提升GC說佔CPU的比,以最大話的減少heap。

2、CMS GC Incremental mode

 當要使用 concurrent low pause collector時,在java的opt里加上 -XX:+UseConcMarkSweepGC。concurrent low pause collector還有一種爲CPU少的機器準備的模式,叫Incremental mode。這種模式使用一個CPU來在程序運行的過程當中GC,只用不多的時間暫停程序,檢查對象存活。

在Incremental mode裏,每一個收集過程當中,會暫停兩次,第二次略長。第一次用來,簡單從root查詢存活對象。第二次用來,詳細檢查存活對象。整個過程以下:

* stop all application threads; do the initial mark; resume all application threads(第一次暫停,初始話標記)
* do the concurrent mark (uses one procesor for the concurrent work)(運行是標記)
* do the concurrent pre-clean (uses one processor for the concurrent work)(準備清理)
* stop all application threads; do the remark; resume all application threads(第二次暫停,標記,檢查)
* do the concurrent sweep (uses one processor for the concurrent work)(運行過程當中清理)
* do the concurrent reset (uses one processor for the concurrent work)(復原)

當要使用Incremental mode時,須要使用如下幾個變量:

-XX:+CMSIncrementalMode default: disabled 啓動i-CMS模式(must with -XX:+UseConcMarkSweepGC)
-XX:+CMSIncrementalPacing default: disabled 提供自動校訂功能
-XX:CMSIncrementalDutyCycle=<N> default: 50 啓動CMS的上線
-XX:CMSIncrementalDutyCycleMin=<N> default: 10 啓動CMS的下線
-XX:CMSIncrementalSafetyFactor=<N> default: 10 用來計算循環次數
-XX:CMSIncrementalOffset=<N> default: 0 最小循環次數(This is the percentage (0-100) by which the incremental mode duty cycle is shifted to the right within the period between minor collections.)
-XX:CMSExpAvgFactor=<N> default: 25 提供一個指導收集數

SUN推薦的使用參數是:

-XX:+UseConcMarkSweepGC \
-XX:+CMSIncrementalMode \
-XX:+CMSIncrementalPacing \
-XX:CMSIncrementalDutyCycleMin=0 \
-XX:CMSIncrementalDutyCycle=10 \
-XX:+PrintGC Details \
-XX:+PrintGCTimeStamps \
-XX:-TraceClassUnloading
注:若是使用throughput collector和concurrent low pause collector,這兩種垃圾收集器,須要適當的挺高內存大小,覺得多線程作準備。

3、如何選擇collector

app運行在單處理器機器上且沒有pause time的要求,讓vm選擇單線程收集器serial collector。

重點考慮peak application performance(高性能),沒有pause time太嚴格要求,選擇並行收集器parallel collector。

重點考慮response time,pause time要小,選擇併發收集器concurrent collector。

 

鳴謝:特別感謝做者周志明提供的技術支持!

相關文章
相關標籤/搜索