天天看點

JVM垃圾回收-Serial收集器& ParNew收集器& Parallel收集器& CMS收集器(五)Serial垃圾收集器(串型回收)ParNew垃圾收集器(并行回收)Parallel垃圾收集器(并行回收)CMS垃圾收集器(并發回收)

Serial GC& ParNew GC& Parallel GC& CMS GC

  • Serial垃圾收集器(串型回收)
    • 1. Serial新生代收集器
    • 2. Serial Old老年代收集器
  • ParNew垃圾收集器(并行回收)
  • Parallel垃圾收集器(并行回收)
  • CMS垃圾收集器(并發回收)

Serial垃圾收集器(串型回收)

  • Serial GC是最基礎, 曆史最悠久的垃圾收集器, Jdk1.3.1之前回收新生代的唯一選擇, 它是一個單線程的串行收集器, 當開始回收時, 将引起所有使用者線程 STW, 直到結束
  • 在 JVM的 Client模式下, 它是預設收集器(Serial& Serial Old)

1. Serial新生代收集器

  • 複制算法

2. Serial Old老年代收集器

  • 标記-壓縮算法
  • 在 JVM的 Server模式下, 1. 主要與 Parallel Scavenge(新年代并行回收)配合使用(Jdk14開始棄用). 2. 或作為 CMS(老年代并發回收)收集器的後備垃圾回收方案(Jdk14開始 CMS被棄用)
JVM垃圾回收-Serial收集器& ParNew收集器& Parallel收集器& CMS收集器(五)Serial垃圾收集器(串型回收)ParNew垃圾收集器(并行回收)Parallel垃圾收集器(并行回收)CMS垃圾收集器(并發回收)
優點: 在單核 CPU環境中選擇它, 由于沒有線程間上下文切換的開銷, 性能比任何收集器都要好
  • 開啟參數

    -XX:+UseSerialGC

    後, 預設開啟 Serial Old老年代收集器, 也就是會同時生效

ParNew垃圾收集器(并行回收)

  1. 如果 Serial GC是新年代的單線程收集器, 那麼 ParNew收集器, 則是 Serial收集器的多線程版本
  2. 針對新年代的回收
  3. 采用的複制算法, 同時垃圾回收時, 也會引起所有的使用者線程的 STW
  4. 除 Serial GC外, 目前隻有 ParNew GC能與 CMS收集器配合使用(Jdk14開始 CMS被棄用)
JVM垃圾回收-Serial收集器& ParNew收集器& Parallel收集器& CMS收集器(五)Serial垃圾收集器(串型回收)ParNew垃圾收集器(并行回收)Parallel垃圾收集器(并行回收)CMS垃圾收集器(并發回收)
相對于 Serial GC優勢是在多核 CPU環境下, 可以充分利用處理性能, 更快的回收垃圾, 同時提升程式的吞吐量
  • 開啟參數

    -XX:+UseParNewGC

    , 表示新年代使用 ParNew收集器, 不影響老年代
  • 設定老年代為 CMS(并發收集器)

    -XX:+UseConcMarkSweepGC

  • 設定線程數

    -XX:ParallelGCThreads=8

    , 預設與 CPU的核數是相同的, 建議設定小于核數, 不建議設大于核數.

    當核數大于8個 ParallelGCThreads=3 + (5 * cpu core / 8)

Parallel垃圾收集器(并行回收)

  • HotSpot的新年代中, 除了 ParNew收集器是基于并行回收以外, Parallel Scavenge收集器同樣也采用了并行回收, 複制算法, 還有當垃圾回收時, 也會引起所有使用者線程的 STW
  • Parallel Scavenge收集器是吞吐量優先的收集器, 差別于 ParNew收集器, 它具有自适應調節政策(如 新年代大小 Eden和 Survivor的比例, 還有晉升老年代的對象年齡等參數會被自動調整)
  • 從 Jdk6開始提供了, 與它配套的老年代收集器 Parallel Old(它也是并行回收, 采用的算法是标記-壓縮算法, 同時也會引起 STW)
  • (1) Parallel Scavenge和 Parallel Old的組合, 在 Jdk8的 Server模式下是預設收集器
  • (2) 這個組合比較适合在高性能伺服器使用

    * 注: 雖然可以搭配成 Parallel Scavenge + Serial Old, 不過此配套不如 ParNew + CMS, 是以如果想要使用 Parallel Scavenge就應該與 Parallel Old搭配

JVM垃圾回收-Serial收集器& ParNew收集器& Parallel收集器& CMS收集器(五)Serial垃圾收集器(串型回收)ParNew垃圾收集器(并行回收)Parallel垃圾收集器(并行回收)CMS垃圾收集器(并發回收)
  • 開啟新年代回收參數

    -XX:+UseParallelGC

    , 開啟老年代回收參數 -XX:+UseParallelOldGC. 此兩參數隻要開啟一個, 另一個也會被自動開啟
  • 設定線程數

    -XX:ParallelGCThreads=8

    , 預設與 CPU的核數是相同的, 建議設定小于核數, 不建議設大于核數.

    當核數大于8個 ParallelGCThreads=3 + (5 * cpu core / 8)

  • 設定收集器最大停頓時間

    -XX:MaxGCPauseMillis=200

    (即 STW的時間, 機關為毫秒)
  1. 為了盡可能地将停頓時間控制在 MaxGCPauseMillis以内, 收集器在工作時會自動調整堆裡的相關參數
  2. 每次停頓時間越短對于使用者的體驗是越好的. 但一般停頓時間短意味着回收相對頻繁, 因而影響吞吐量. 作為吞吐量優先的收集器, 不宜與設定太小
  3. 該參數使用需謹慎
  • 設定垃圾回收時間占總時間的比率(吞吐量)

    -XX:GCTimeRatio=N

    , 取值範圍是大于0, 且小于100的整數, 預設值為99, 也就是允許最大1%(即1 / ( 1 + N))的垃圾收集時間.

    (*) 此參與

    -XX:MaxGCPauseMillis

    有一定沖突性. 是以在權衡參數時要抓住性能瓶頸
  • 開啟 Parallel Scavenge收集器的自适應調節政策

    -XX:+UseAdaptiveSizePolicy

    (此參預設開啟)

    (-) 自動調節新年代大小 Eden和 Survivor的比例, 還有晉升老年代的對象年齡等參數, 從此達到吞吐量, 暫停時間和記憶體占用之間的平衡

    (-) 在調優比較困難的場合, 可以隻指定虛拟機的堆大小, 目标吞吐量 GCTimeRatio和停頓時間 MaxGCPauseMillis, 直接讓虛拟機自适應調節

CMS垃圾收集器(并發回收)

  • Jdk5時 HotSpot推出了 CMS(Concurrent Mark-Sweep)收集器, 它是響應速度優先的低延遲垃圾收集器, 采用的算法是标記-清除算法, 還有依然存在 STW
  • CMS垃圾回收4個階段:
  1. 初始标記(Initial-Mark)階段: 标記 GC Roots能夠直接關聯的對象. 此階段使用者線程會引起 STW, 直到初始标記完成
  2. 并發标記(Concurrent-Mark)階段: 周遊第1階段标記的可達對象, 進行根檢查後, 再标記為活躍的對象. 此階段是與使用者線程是并發進行的
  3. 重新标記(Remark)階段: 由于在并發标記階段中, 使用者線程和垃圾收集線程(标記階段)同時或交叉運作, 進而導緻了标記産生變動的那一部分的對象标記記錄做修正. 此階段使用者線程會引起 STW, 直到标記完成
  4. 并發清楚(Concurrent-Sweep)階段: 回收在标記階段判斷為不可達的對象, 由于用的标記-清除算法, 是以不需要移動存活對象, 是以也是并發進行的
  • 以上階段中并發标記和并發清除階段是最耗費時間的, 但兩個都是并發回收(非獨占式), 是以整體的互動是低停頓的
JVM垃圾回收-Serial收集器& ParNew收集器& Parallel收集器& CMS收集器(五)Serial垃圾收集器(串型回收)ParNew垃圾收集器(并行回收)Parallel垃圾收集器(并行回收)CMS垃圾收集器(并發回收)
  • 優點: 并發回收, 低延遲
  • 缺點:
  1. 由于采用的是标記-清除算法, 是以會産生記憶體碎片
  2. 在并發回收時, 雖然不會一次性停頓長時間影響互動體驗, 但是因為回收線程與使用者線程交替并發工作的, 是以吞吐量會下降
  3. 在并發标記階段, 對于浮動垃圾是有遺漏的, 無法及時回收隻能下次 GC時做标記, 并回收

* 注: 由于 CMS垃圾回收是并發進行的, 是以在回收過程中, 還應該確定應用程式有足夠的記憶體可用. 是以, CMS收集器不是等到老年代滿後再進行收集的, 而是當堆記憶體使用率達到某一門檻值時, 便開始進行回收. 要是運作期間預留的記憶體依然不夠, 就會出現一次 Concurrent Mode Failure, 然後虛拟機會自動采用 Serial Old收集器進行 Full GC

  • 開啟 CMS垃圾收集器

    -XX:+UseConcMarkSweepGC

    後, 将自動開啟新年代的收集器

    -XX:+UseParNewGC

    即: ParNew(Young區) + CMS(Old區) + Serial Old(當 Concurrent Mode Failure時用于觸發 Full GC)的組合
  • 設定堆記憶體使用率的門檻值

    XX:CMSInitiatingOccupanyFraction=N

    , 一旦到達該門檻值即觸發回收

    (-) Jdk6之前預設值為68%, 之後92%

    (*) 如果記憶體增長緩慢, 則可以設定一個稍大的值, 可以有效降低 CMS的觸發頻率. 反之, 如果應用程式記憶體增長很快, 則應該降低這個門檻值, 以避免頻繁觸發老年代串行收集器

  • 開啟

    -XX:+UseCMSCompactAtFullCollection

    當 Full GC後再對記憶體空間進行壓縮整理, 由于壓縮整理過程無法并發執行, 是以産生的問題是停頓時間變的更長(Jdk8開始此參已過時)
  • 設定次數

    -XX:CMSFullGCsBeforeCompaction=N

    在上面的配置開啟的前提下, 執行了N次 Full GC後對記憶體空間進行壓縮整理(Jdk8開始此參已過時)
  • 設定 CMS的線程數

    -XX:ParallelCMSThreads=2

    , 預設啟動的線程數是(

    ParallelGCThreads + 3) / 4 = 2

    ; ParallelGCThreads是新年代 ParNew并行收集器的線程數
如果您覺得有幫助,歡迎點贊哦 ~ 謝謝!!