JVM - 垃圾回收器概述

[toc]算法

既然選擇了遠方,即便天寒地凍,路遙馬亡,我本就一無全部,又有何懼。

串行收集器

  1. 單線程、獨佔式進行垃圾回收
  2. 獨佔式:應用程序線程會中止工做,只有垃圾回收線程在工做,即 stop the world
  3. 在並行能力較差的機器上,會有更好的性能表現。

新生代串行收集器

  1. 新生代串行收集器使用的是 複製算法
  2. 使用 -XX:UseSerialGC, -XX:+UseConcMarkSweepGC -XX:-UseParNew 啓用
  3. GC 日誌以下所示
[GC (Allocation Failure) [DefNew: 67932K->0K(78720K), 0.0002327 secs] 68792K->859K(253504K), 0.0002491 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

老年代串行收集器

  1. 老年代串行收集器使用的是 標記-壓縮算法
  2. 使用 -XX:UseSerialGC-XX:+UseParNewGC 啓用
  3. GC 日誌以下
[Full GC (Allocation Failure) [Tenured: 10250K->10249K(15360K), 0.0187416 secs] 10250K->10249K(19968K), [Metaspace: 9228K->9228K(1058816K)], 0.0187608 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]

並行收集器

ParNew

  1. 新生代垃圾回收器
  2. 新生代串行收集器的多線程版本
  3. 與新生代串行收集器的區別僅在於垃圾回收時,是多線程並行。
  4. 使用 -XX:UseParNew-XX:UseConcMarkSweepGC 啓用
  5. GC 日誌以下
[GC (Allocation Failure) [ParNew: 82K->24K(4608K), 0.0003178 secs][Tenured: 15353K->10251K(15360K), 0.0185459 secs] 15435K->10251K(19968K), [Metaspace: 8855K->8855K(1056768K)], 0.0188925 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]

ParallelGC

  1. 新生代垃圾回收器,使用 複製算法
  2. ParNew 相比,ParallelGC 更關注吞吐量
  3. -XX:MaxGCPauseMillis:設置最大垃圾停頓時間。例:-XX:MaxGCPauseMillis=200
  4. -XX:GCTimeRatio:設置吞吐量大小。取值範圍爲 0~100 的整數。若值爲 n,那麼 JVM 將花費不超過 1/(1+n) 的時間在 GC 上。例:-XX:GCTimeRatio=99
  5. -XX:+UseAdaptiveSizePolicy:自適應調整 新生代大小、eden 和 survivor 比例,以及晉升老年代對象年齡等參數
  6. 可經過 -XX:+UseParallelGC-XX:+UseParallelOldGC 啓用
  7. GC 日誌以下
[GC (Allocation Failure) [PSYoungGen: 2410K->512K(4608K)] 12650K->10947K(19968K), 0.0016662 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]

ParallelOldGC

  1. 老年代垃圾回收器,使用 標記-壓縮算法
  2. ParallelGC 一致,關注系統吞吐量ParallelOldGCjdk1.6後(包括) 纔可使用
  3. -XX:ParalleGCThreads:設置 GC 時,並行的線程數
  4. 可經過 -XX:+UseParallelGC-XX:+UseParallelOldGC 啓用
  5. GC 日誌以下
[Full GC (Allocation Failure) [PSYoungGen: 480K->0K(4608K)] [ParOldGen: 10499K->626K(15360K)] 10979K->626K(19968K), [Metaspace: 3063K->3063K(1056768K)], 0.0043604 secs] [Times: user=0.02 sys=0.00, real=0.00 secs]

CMS

CMS 是一款 低停頓老年代 垃圾收集器。通常與 Serial, ParNew 新生代收集器一塊兒工做,默認是 ParNew
工做流程細化爲如下幾個步驟多線程

  1. 初始化標記(stop the world
  2. 併發標記
  3. 預清理
  4. 從新標記(stop the world
  5. 併發清理
  6. 併發重置狀態等待下次 CMS 觸發

初始化標記

  1. stop the world
  2. 標記老年代 GC Root 對象
  3. 標記新手代引用老年代的對象

併發標記

  1. 與應用線程併發執行,從上一步標記的節點順着引用鏈路往下標記
  2. 併發標記過程當中,老年代會產生新的對象、老年代引用會變動等等。爲了提升從新標記的效率,這些對象所在的 card 會被標記爲 dirty
  3. 這一階段,可能會致使 concurrent mode failure

預清理

與應用線程併發執行,處理上一個階段被標記爲 dirty 的對象。該階段爲了減小 從新標記 產生的停頓時間,有可能會等待一次 ygc併發

從新標記

  1. stop the world
  2. dirtyroot 繼續往下標記可達對象

併發清理

  1. 與應用線程併發執行
  2. 採用 標記-清除 算法將垃圾清除

concurrent mode failure

在併發清理階段,提到,有可能會發生 concurrent mode failure 現象。
出現該現象的本質緣由以下:
老年代沒有足夠的空間分配對象,從而致使使用 Serial Old 垃圾收集器觸發一次 Full GC性能

主要參數

  1. -XX:ConcGCThreads, -XX:ParallelCMSThreads
    CMS 默認啓動的併發線程是(ParallelGCThreads + 3)/ 4. ParallelGCThreads 表示新生代 GC 線程數量。-XX:ConcGCThreads -XX:ParallelCMSThreads 可手動指定 CMS 併發線程
  2. -XX:+CMSScavengeBeforeRemark
    在進行 從新標記 階段時,會執行一次 ygc
  3. -XX:CMSInitiatingOccupancyFraction
    默認68,當老年代空間使用率達到該值時,會執行一次 CMS GC
  4. -XX:+UseCMSCompactAtFullCollection
    使 CMS 在垃圾收集完成後,進行一次內存碎片整理,碎片整理會 stop the world
  5. -XX:CMSFullGCsBeforeCompaction
    默認0,設定進行多少次 CMS 回收後,進行一次內存壓縮
  6. -XX:CMSMaxAbortablePrecleanTime
    默認 5000 毫秒,預清理階段,等待 ygc 最大時間
  7. -XX:+CMSClassUnloadingEnabled
    容許回收 Class

垃圾回收器組合

筆者沒法在 jdk1.8 上,測試出 serial + parallel old 組合。
image.png測試

參考

CMS垃圾收集器spa

相關文章
相關標籤/搜索