深入淺出 JVM GC(4)常用 GC 參數介紹

# 前言

從前面的3篇文章中,我們分析了5個垃圾收集器,還有一些 GC 的算法,那么,在 GC 調優中,我們肯定會先判斷哪里出現的問題,然后再根據出現的問題進行調優,而調優的手段就是 JVM 提供給我們的那些參數或者說選項,這些參數將會改變 GC 的運行方式。因此,他們顯得極為重要。

我們將每一個垃圾收集器相關的參數一個一個娓娓道來,注意,樓主推薦一個小程序:前阿里 JVM 大神寒泉子的公眾號里面有個小程序------JVM Pocket,這個小程序介紹了所有的 JVM 參數的作用,你可以在里面搜索你想知道的參數,也可以把你了解的參數寫上去供大家參考。公眾號:lovestblog。

值得注意的一點是,這些參數可能會重復,還記得我們之前的那張圖嗎,樓主覺得有必要再發一次:

可以看到,這些收集器會有一些重復,而且,某些參數也是會作用于所有的處理器,因此,我們下面的介紹可能會有一些重復。

還有一點就是,JVM 為我們設置了很多默認的參數,但是,如果可以的話,還是建議使用顯式的聲明,這樣更能表達意圖。否則,別人不一定知道我們是否知道這些默認值。

我們開始我們的參數之旅吧!

# 1. Serial 收集器參數

串行收集器,client 的默認收集器,分為年輕代 Serial 和老年代 Serial Old 收集器。

  1. -XX:+UseSerialGC 這個參數就是可以指定使用新生代串行收集器和老年代串行收集器, “+” 號的意思是ture,開啟,反之,如果是 “-”號,則是關閉。

  2. -XX:+UseParNewGC 新生代使用 ParNew 回收器,老年代使用串行收集器。

  3. -XX:+UseParallelGC 新生代私用 ParallelGC 回收器,老年代使用串行收集器。

而 Serial 收集器出現的日志為 DefNew .

# 2. ParNew 收集器參數

并行收集器是 Serial 的多線程版本,在 CPU 并行能力強大的計算機上有很大優勢。

其中:

  1. -XX:+UseParNewGC 上面說過了,新生代使用 ParNew 收集器,老年代使用串行收集器。

  2. -XX:+UseConcMarkSweepGC: 新生代使用 ParNew 回收器,老年代使用 CMS。

  3. -XX:ParallelGCThreads={value} 這個參數是指定并行 GC 線程的數量,一般最好和 CPU 核心數量相當。默認情況下,當 CPU 數量小于8, ParallelGCThreads 的值等于 CPU 數量,當 CPU 數量大于 8 時,則使用公式:3+((5*CPU)/ 8);同時這個參數只要是并行 GC 都可以使用,不只是 ParNew。

而 ParNew 的 GC 日志則表吸納出 ParNew。

# 3. PS 收集器參數

全稱 Parallel Scavenge 收集器,該收集器是 Java 8 的默認收集器,因為它能夠根據系統當前狀態給出吞吐量最高的GC 配置。所以,在一些手工調優復雜的場合或者對實時性要求不高的場合,可以使用該處理器。

有哪些參數呢?

  1. -XX:MaxGCPauseMillis 設置最大垃圾收集停頓時間,他的值是一個大于0的整數。ParallelGC 工作時,會調整 Java 堆大小或者其他的一些參數,盡可能的把停頓時間控制在 MaxGCPauseMillis 以內。如果為了將停頓時間設置的很小,將此值也設置的很小,那么 PS 將會把堆設置的也很小,這將會到值頻繁 GC ,雖然系統停頓時間小了,但總吞吐量下降了。

  2. -XX:GCTimeRatio 設置吞吐量大小,他的值是一個0 到100之間的整數,假設 GCTimeRatio 的值是 n ,那么系統將花費不超過 1/(1+n) 的時間用于垃圾收集,默認 n 是99,即不超過1% 的時間用于垃圾收集。

  3. -XX:+UseParallelGC 新生代使用 ParallelGC 回收器,老年代使用串行回收器。

  4. -XX:+UseParallelOldGC 新生代使用 ParallelGC 回收器,老年代使用 ParallelOldGC 回收器。

  5. -XX:UseAdaptiveSizePolicy: 打開自適應策略。在這種模式下,新生代的大小,eden 和 Survivor 的比例,晉升老年代的對象年齡等參數會被自動調整。以達到堆大小,吞吐量,停頓時間的平衡點。

聰明的同學相比看出來了,1 和 2 兩個參數是矛盾的。因為吞吐量和停頓時間就是矛盾的。所以,要根據應用的特性來進行設置,以達到最優水平。

同時,Parallel Old 收集器也是一種關注吞吐量的并行的老年代回收器。

  1. -XX:+UseParallelOldGC 新生代使用 ParallelGC 回收器,老年代使用 ParallelOldGC 回收器。該參數可以啟用 ParallelOldGC。

  2. -XX:ParallelGCGThreads 同時可以指定該參數設置并行線程數量。

而 PS 處理器的 GC 日志則是 PSYoungGen。

# 4. CMS 收集器參數

CMS 處理器關注的是停頓時間。全稱 Concurrent Mark Sweep。因為該處理器較為復雜,因此可以使用較多參數。

  1. -XX:-CMSPrecleaningEnabled 不進行預清理,度過我們之前的文章的都知道,CMS 在并發標記和重新標記的這段時間內,會有一個預清理的工作,而這個通過會嘗試5秒之內等待來一次 YGC。以免在后面的重新標記階段耗費大量時間來標記新生代的對象。

  2. -XX:+UseConcMarkSweepGC 此參數將啟動 CMS 回收器。默認新生代是 ParNew,也可以設置 Serial 為新生代收集器。該參數等價于 -Xconcgc。

  3. -XX:ParallelGCThreads 由于是并行處理器,當然也可以指定線程數。默認并發線程數是:(ParallelGCThreads + 3)/ 4)。

  4. -XX:ConcGCThreads 或者 -XX:ParallelCMSThreads ;除了上面設置線程的方式,你也可以通過這個兩個參數任意一個手工設定 CMS 并發線程數。

  5. -XX:CMSInitiatingOccupancyFraction 由于 CMS 回收器不是獨占式的,在垃圾回收的時候應用程序仍在工作,所以需要留出足夠的內存給應用程序,否則會觸發 FGC。而什么時候運行 CMS GC 呢?通過該參數即可設置,該參數表示的是老年代的內存使用百分比。當達到這個閾值就會執行 CMS。默認是68。 如果老年代內存增長很快,建議降低閾值,避免 FGC,如果增長慢,則可以加大閾值,減少 CMS GC 次數。提高吞吐量。

  6. -XX:+UseCMSCompactAtFullCollection 由于 CMS 使用標記清理算法,內存碎片無法避免。該參數指定每次 CMS 后進行一次碎片整理。

  7. -XX:CMSFullGCsBeforeCompaction 由于每次進行碎片整理將會影響性能,你可以使用該參數設定多少次 CMS 后才進行一次碎片整理,也就是內存壓縮。

  8. -XX:+CMSClassUnloadingEnabled 允許對類元數據進行回收。

  9. -XX:CMSInitiatingPermOccupancyFraction 當永久區占用率達到這一百分比時,啟動 CMS 回收(前提是 -XX:+CMSClassUnloadingEnabled 激活了)。

  10. -XX:UseCMSInitiatingOccupancyOnly 表示只在到達閾值的時候才進行 CMS 回收。

  11. XX:CMSWaitDuration=2000 由于CMS GC 條件比較簡單,JVM有一個線程定時掃描Old區,時間間隔可以通過該參數指定(毫秒單位),默認是2s。

CMS 的 GC 日志 就是 CMS。

# 5. G1 收集器參數

作為 Java 9 的默認垃圾收集器,該收集器和之前的收集器大不相同,該收集器可以工作在young 區,也可以工作在 old 區。有哪些參數呢?

  1. -XX:+UseG1GC 開啟 G1 收集器。

  2. -XX:MaxGCPauseMillis 用于指定最大停頓時間,如果任何一次停頓超過這個設置值時,G1 就會嘗試調整新生代和老年代的比例,調整堆大小,調整晉升年齡的手段,試圖達到目標。和 PS 一樣,停頓時間小了,對應的吞吐量也會變小。這點值得注意。

  3. -XX:ParallelGCThreads 由于是并行并發的,可以指定GC 工作線程數量。

  4. -XX:InitiatingHeapOccupancyPercent 該參數可以指定當整個堆使用率達到多少時,觸發并發標記周期的執行。默認值時45,即當堆的使用率達到45%,執行并發標記周期,該值一旦設置,始終都不會被 G1修改。也就是說,G1 就算為了滿足 MaxGCPauseMillis 也不會修改此值。如果該值設置的很大,導致并發周期遲遲得不到啟動,那么引起 FGC 的幾率將會變大。如果過小,則會頻繁標記,GC 線程搶占應用程序CPU 資源,性能將會下降。

  5. -XX:GCPauseIntervalMillis 設置停頓時間間隔。

# 6. 一些通用參數

在 GC 調優中,還有一些通用的參數。通常是我們的好幫手。

  1. -XX:-+DisableExplicitGC 禁用 System.gc(),由于該方法默認會觸發 FGC,并且忽略參數中的 UseG1GC 和 UseConcMarkSweepGC,因此必要時可以禁用該方法。

  2. -XX:+ExplicitGCInvokesConcurrent 該參數可以改變上面的行為,也就是說,System.gc() 后不使用 FGC ,而是使用配置的并發收集器進行并發收集。注意:使用此選項就不要 使用 上面的選項。

  3. -XX:-ScavengeBeforeFullGC 由于大部分 FGC 之前都會 YGC,減輕了 FGC 的壓力,縮短了 FGC 的停頓時間,但也可能你不需要這個特性,那么你可以使用這個參數關閉,默認是 ture 開啟。

  4. -XX:MaxTenuringThreshold={value} 新生代 to 區的對象在經過多次 GC 后,如果還沒有死亡,則認為他是一個老對象,則可以晉升到老年代,而這個年齡(GC 次數)是可以設置的,有就是這個參數。默認值時15。超過15 則認為是無限大(因為age變量時4個 bit,超過15無法表達)。但該參數不是唯一決定對象晉升的條件。當 to 區不夠或者改對象年齡已經達到了平均晉升值或者大對象等等條件。

  5. -XX:TargetSurvivorRatio={value} 決定對何時晉升的不僅只有 XX:MaxTenuringThreshold 參數,如果在 Survivor 空間中相同年齡所有對象大小的總和大魚 Survivor 空間的一半(默認50%),年齡大于或等于該年齡的對象就可以直接進入老年代。無需在乎 XX:MaxTenuringThreshold參數。因此,MaxTenuringThreshold 只是對象晉升的最大年齡。如果將 TargetSurvivorRatio 設置的很小,對象將晉升的很快。

  6. -XX:PretenureSizeThresholds={value} 除了年齡外,對象的體積也是影響晉升的一個關鍵,也就是大對象。如果一個對象新生代放不下,只能直接通過分配擔保機制進入老年代。該參數是設置對象直接晉升到老年代的閾值,單位是字節。只要對象的大小大于此閾值,就會直接繞過新生代,直接進入老年代。注意:這個參數只對 Serial 和 ParNew 有效,ParallelGC 無效,默認情況下該值為0,也就是不指定最大的晉升大小,一切有運行情況決定。

  7. -XX:-UseTLAB 禁用線程本地分配緩存。TLAB 的全稱是 Thread LocalAllocation Buffer ,即線程本地線程分配緩存,是一個線程私有的內存區域。該設計是為了加速對象分配速度。由于對象一般都是分配在堆上,而對是線程共享的。因此肯定有鎖,雖然使用 CAS 的操作,但性能仍有優化空間。通過為每一個線程分配一個 TLAB 的空間(在 eden 區),可以消除多個線程同步的開銷。默認開啟。

  8. -XX:TLABSize 指定 TLAB 的大小。

  9. -XX:+PrintTLAB 跟蹤 TLAB 的使用情況。用以確定是用多大的 TLABSize。

  10. -XX:+ResizeTLAB 自動調整 TLAB 大小。

同時,對象也可能會在棧上分配,棧上分配,TLAB 分配,堆分配,他們的流程如下:

對象分配流程

還有一些開啟 GC 日志的參數,是 GC 調優不可或缺的工具。

  1. -XX:+PrintGCDateStamps 打印 GC 日志時間戳。

  2. -XX:+PrintGCDetails 打印 GC 詳情。

  3. -XX:+PrintGCTimeStamps: 打印此次垃圾回收距離jvm開始運行的所耗時間。

  4. -Xloggc:<filename> 將垃圾回收信息輸出到指定文件

  5. -verbose:gc 打印 GC 日志

  6. -XX:+PrintGCApplicationStopedTime 查看 gc 造成的應用暫停時間

  7. XX:+PrintTenuringDistribution, 對象晉升的日志

  8. -XX:+HeapDumpOnOutOfMemoryError 內存溢出時輸出 dump 文件。

# 總結

好了,我們已經將一些常用的 GC 參數介紹了,當然會有遺漏的,如有遺漏或者介紹有誤的,請告知本人。這些參數不僅僅是為了服務大家,同時也是自己做的一個總結,以后就不用到處找了。說白了這就是寫博客的好處:總結了自己,也做了備份,同時也可能幫助了別人。

Good Luck!!!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,494評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,714評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,410評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,940評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,776評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,210評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,654評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容

  • 原文閱讀 前言 這段時間懈怠了,罪過! 最近看到有同事也開始用上了微信公眾號寫博客了,挺好的~給他們點贊,這博客我...
    碼農戲碼閱讀 6,003評論 2 31
  • 這篇文章是我之前翻閱了不少的書籍以及從網絡上收集的一些資料的整理,因此不免有一些不準確的地方,同時不同JDK版本的...
    高廣超閱讀 15,650評論 3 83
  • # 前言 在 深入淺出 JVM GC(2) 中,我們介紹了一些 GC 算法,GC 名詞,同時也留下了一個問題,就...
    莫那一魯道閱讀 1,129評論 1 4
  • Java 虛擬機有自己完善的硬件架構, 如處理器、堆棧、寄存器等,還具有相應的指令系統。JVM 屏蔽了與具體操作系...
    尹小凱閱讀 1,700評論 0 10
  • http://www.cnblogs.com/angeldevil/p/3801189.html值得一看 Clas...
    snail_knight閱讀 1,439評論 1 0