各類GC及觸發條件

針對HotSpot VM的實現,它裏面的GC其實準確分類只有兩大種:

  • Partial GC:並不收集整個GC堆的模式
  • Young GC:只收集young gen的GC
  • Old GC:只收集old gen的GC。只有CMS的concurrent collection是這個模式
  • Mixed GC:收集整個young gen以及部分old gen的GC。只有G1有這個模式
  • Full GC:收集整個堆,包括young gen、old gen、perm gen(如果存在的話)等所有部分的模式。

Major GC通常是跟full GC是等價的,收集整個GC堆。但因爲HotSpot VM發展了這麼多年,外界對各種名詞的解讀已經完全混亂了,當有人說“major GC”的時候一定要問清楚他想要指的是上面的full GC還是old gen。

最簡單的分代式GC策略,按HotSpot VM的serial GC的實現來看,觸發條件是:
**young GC:**當young gen中的eden區分配滿的時候觸發。注意young GC中有部分存活對象會晉升到old gen,所以young GC後old gen的佔用量通常會有所升高。
full GC:當準備要觸發一次young GC時,如果發現統計數據說之前young GC的平均晉升大小比目前old gen剩餘的空間大,則不會觸發young GC而是轉爲觸發full GC(因爲HotSpot VM的GC裏,除了CMS的concurrent collection之外,其它能收集old gen的GC都會同時收集整個GC堆,包括young gen,所以不需要事先觸發一次單獨的young GC);或者,如果有perm gen的話,要在perm gen分配空間但已經沒有足夠空間時,也要觸發一次full GC;或者System.gc()、heap dump帶GC,默認也是觸發full GC。這就是FullGC的觸發條件
HotSpot VM裏其它
非併發
GC的觸發條件複雜一些,不過大致的原理與上面說的其實一樣。
當然也總有例外。Parallel Scavenge(-XX:+UseParallelGC)框架下,默認是在要觸發full GC前先執行一次young GC,並且兩次GC之間能讓應用程序稍微運行一小下,以期降低full GC的暫停時間(因爲young GC會盡量清理了young gen的死對象,減少了full GC的工作量)。這是HotSpot VM裏的奇葩嗯。

併發GC的觸發條件就不太一樣。以CMS GC爲例,它主要是定時去檢查old gen的使用量,當使用量超過了觸發比例就會啓動一次CMS GC,對old gen做併發收集。這裏就是隻回收老年代了!

從攜程apollo拷貝過來的JVM參數,看一下他們用了哪些JVM參數

-Xms6144m -Xmx6144m -Xss256k -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=384m -XX:NewSize=4096m -XX:MaxNewSize=4096m -XX:SurvivorRatio=8
-XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:MaxTenuringThreshold=9 -XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:+ScavengeBeforeFullGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=9 -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSClassUnloadingEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSPermGenSweepingEnabled -XX:CMSInitiatingPermOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrent -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -Duser.timezone=Asia/Shanghai -Dclient.encoding.override=UTF-8 -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom

UseCMSCompactAtFullCollection和CMSFullGCsBeforeCompaction是搭配使用,兩個參數缺一不可,才能實現指定次數Full GC後對老年代進行壓縮,因爲老年代是標記清除。

-XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark指導垃圾回收機制在進行Full GC和CMS remark phase之前收集年輕態。其結果是提升性能,因爲在年輕態和老態之間不存在檢查引用。

-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=

缺省的 CMS GC使用的啓發式規則觸發垃圾回收,這會讓GC不太能預測,一般直至老生代空間被幾乎佔滿後纔會啓動垃圾回收,Initiating設置能夠使得在老生代變滿之前完成回收,避免Full GC (這就意味着整個應用程序暫停無響應stop-the-world pause). -XX:+UseCMSInitiatingOccupancyOnly 阻止使用啓發式規則 -XX:CMSInitiatingOccupancyFraction 通過JVM應該在什麼時候啓動觸發回收,它會在heap中創建一個buffer,這個緩衝當CMS工作時能用數據填充,其內存被消耗的速度百分比可衡量老生代生產環境中的消耗。這個百分比數值應該小心選擇,太小CMS太頻繁,太大CMS啓動頻率太少,併發模式可能會失敗。

XX:+CMSParallelRemarkEnabled

啓動併發標記,提高效率。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章