JVM CMS 經常使用參數配置(修訂)

-XX:+UseConcMarkSweepGC
該標誌首先是激活CMS收集器。默認HotSpot JVM使用的是並行收集器。
-XX:UseParNewGC
當使用CMS收集器時,該標誌激活年輕代使用多線程並行執行垃圾回收。這使人很驚訝,咱們不能簡單在並行收集器中重用-XX:UserParNewGC標誌,由於概念上年輕代用的算法是同樣的。然而,對於CMS收集器,年輕代GC算法和老年代GC算法是不一樣的,所以年輕代GC有兩種不一樣的實現,而且是兩個不一樣的標誌。注意最新的JVM版本,當使用-XX:+UseConcMarkSweepGC時,-XX:UseParNewGC會自動開啓。所以,若是年輕代的並行GC不想開啓,能夠經過設置-XX:-UseParNewGC來關掉。
-XX:+CMSParallelRemarkEnabled
採用並行標記方式下降停頓。
-XX:+CMSConcurrentMTEnabled
當該標誌被啓用時,併發的CMS階段將以多線程執行(所以,多個GC線程會與全部的應用程序線程並行工做)。該標誌已經默認開啓,若是順序執行更好,這取決於所使用的硬件,多線程執行能夠經過-XX:-CMSConcurremntMTEnabled禁用。
-XX:ConcGCThreads
標誌-XX:ConcGCThreads=<value>(早期JVM版本也叫-XX:ParallelCMSThreads)定義併發CMS過程運行時的線程數。好比value=4意味着CMS週期的全部階段都以4個線程來執行。儘管更多的線程會加快併發CMS過程,但其也會帶來額外的同步開銷。所以,對於特定的應用程序,應該經過測試來判斷增長CMS線程數是否真的可以帶來性能的提高。若是還標誌未設置,JVM會根據並行收集器中的-XX:ParallelGCThreads參數的值來計算出默認的並行CMS線程數。該公式是ConcGCThreads =(ParallelGCThreads + 3)/4。所以,對於CMS收集器,-XX:ParallelGCThreads標誌不只影響「stop-the-world」垃圾收集階段,還影響併發階段。總之,有很多方法能夠配置CMS收集器的多線程執行。正是因爲這個緣由,建議第一次運行CMS收集器時使用其默認設置, 而後若是須要調優再進行測試。只有在生產系統中測量(或類生產測試系統)發現應用程序的暫停時間的目標沒有達到 , 就能夠經過這些標誌應該進行GC調優。
-XX:CMSInitiatingOccupancyFraction
當堆滿以後,並行收集器便開始進行垃圾收集,例如,當沒有足夠的空間來容納新分配或提高的對象。對於CMS收集器,長時間等待是不可取的,由於在併發垃圾收集期間應用持續在運行(而且分配對象)。所以,爲了在應用程序使用完內存以前完成垃圾收集週期,CMS收集器要比並行收集器更先啓動。由於不一樣的應用會有不一樣對象分配模式,JVM會收集實際的對象分配(和釋放)的運行時數據,而且分析這些數據,來決定何時啓動一次CMS垃圾收集週期。爲了引導這一過程,JVM會在一開始執行CMS週期前做一些線索查找。該線索由-XX:CMSInitiatingOccupancyFraction=<value>來設置,該值表明老年代堆空間的使用率。好比,value=75意味着第一次CMS垃圾收集會在老年代被佔用75%時被觸發。一般CMSInitiatingOccupancyFraction的默認值爲68(以前很長時間的經從來決定的)。
-XX:+UseCMSInitiatingOccupancyOnly
咱們用-XX:+UseCMSInitiatingOccupancyOnly標誌來命令JVM不基於運行時收集的數據來啓動CMS垃圾收集週期。而是,當該標誌被開啓時,JVM經過CMSInitiatingOccupancyFraction的值進行每一次CMS收集,而不只僅是第一次。然而,請記住大多數狀況下,JVM比咱們本身能做出更好的垃圾收集決策。所以,只有當咱們充足的理由(好比測試)而且對應用程序產生的對象的生命週期有深入的認知時,才應該使用該標誌。
-XX:+CMSClassUnloadingEnabled
相對於並行收集器,CMS收集器默認不會對永久代進行垃圾回收。若是但願對永久代進行垃圾回收,可用設置標誌-XX:+CMSClassUnloadingEnabled。在早期JVM版本中,要求設置額外的標誌-XX:+CMSPermGenSweepingEnabled。注意,即便沒有設置這個標誌,一旦永久代耗盡空間也會嘗試進行垃圾回收,可是收集不會是並行的,而再一次進行Full GC。
-XX:+CMSIncrementalMode
該標誌將開啓CMS收集器的增量模式。增量模式常常暫停CMS過程,以便對應用程序線程做出徹底的讓步。所以,收集器將花更長的時間完成整個收集週期。所以,只有經過測試後發現正常CMS週期對應用程序線程干擾太大時,才應該使用增量模式。因爲現代服務器有足夠的處理器來適應併發的垃圾收集,因此這種狀況發生得不多。
-XX:+ExplicitGCInvokesConcurrent和-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
現在,被普遍接受的最佳實踐是避免顯式地調用GC(所謂的「系統GC」),即在應用程序中調用system.gc()。然而,這個建議是無論使用的GC算法的,值得一提的是,當使用CMS收集器時,系統GC將是一件很不幸的事,由於它默認會觸發一次Full GC。幸運的是,有一種方式能夠改變默認設置。標誌-XX:+ExplicitGCInvokesConcurrent命令JVM不管何時調用系統GC,都執行CMS GC,而不是Full GC。第二個標誌-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses保證當有系統GC調用時,永久代也被包括進CMS垃圾回收的範圍內。所以,經過使用這些標誌,咱們能夠防止出現意料以外的「stop-the-world」的系統GC。
-XX:+DisableExplicitGC
然而在這個問題上…這是一個很好提到-XX:+DisableExplicitGC標誌的機會,該標誌將告訴JVM徹底忽略系統的GC調用(無論使用的收集器是什麼類型)。對於我而言,該標誌屬於默認的標誌集合中,能夠安全地定義在每一個JVM上運行,而不須要進一步思考。
-XX:+UseCompressedOops
這個參數用於對類對象數據進行壓縮處理,提升內存利用率。
-XX:MaxGCPauseMillis=50
這個參數用於設置GC暫停等待時間,單位爲毫秒,不要設置太低。
綜上所述,通常狀況下,推薦使用以下的參數設置:
 
-XX:+UseCompressedOops
-XX:MaxGCPauseMillis=50
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled
-XX:+CMSClassUnloadingEnabled
 
相關文章
相關標籤/搜索