05-jvm-GC算法-實際應用

垃圾收集器

若是說收集算法是內存回收的方法論,垃圾收集器就是內存回收的具體實現
複製代碼

性能度量指標

  • 吞吐量:表示系統減去系統回收時間佔總時間的比率,好比,系統運行了100秒,垃圾回收佔用了1秒,那麼吞吐量就是(100-1)/100 = 99%算法

  • 垃圾回收消耗:和吞吐量相反,垃圾回收器消耗指的是垃圾回收器耗時與系統運行總時間的比值編程

  • 停頓時間:指垃圾回收器運行的時候,系統停頓的時間服務器

  • 回收頻率:指垃圾回收器多長時間運行一次,通常來講,對於固定的應用而言,垃圾回收器的頻率應該越低越好,一般增長堆空間能夠有效的下降垃圾回收發生的頻率,可是可能會增長回收產生的停頓時間多線程

  • 反應時間:當一個內存對象被標記爲垃圾對象後到這個對象真正回收所產生的時間併發

    根據這幾個指標,咱們能夠知道,垃圾回收性能好的表現是:吞吐量高,垃圾回收消耗低,停頓時間少,回收頻率低,反應時間快。可是,並無這麼完美的性能表現,這幾個指標有些是互斥的,好比要下降回收頻率,就要擴大空間,可是就會增長停頓時間;一樣要想反應時間快,就必需要提升回收頻率。因此,這些性能的追求就是一個博弈平衡的過程,咱們能夠根據咱們追求的某一方面來進行調優,好比,對於客戶端應用而言,應該儘量下降其停頓時間,給用戶良好的使用體驗,爲此,能夠犧牲垃圾回收的吞吐量;對服務端程序來講,可能會更加關注吞吐量。jvm

按執行機制劃分Java有四種類型的垃圾回收器

image

  1. 串行垃圾回收器(Serial Garbage Collector)
  2. 並行垃圾回收器(Parallel Garbage Collector)
  3. 併發標記掃描垃圾回收器(CMS Garbage Collector)
  4. G1垃圾回收器(G1 Garbage Collector)
  • 每種類型都有各自的優點和劣勢,在很大程度上有所不一樣,能夠給咱們提供徹底不一樣的應用程序性能
  • 咱們編程的時候,能夠經過向jvn傳遞參數,選擇正確的垃圾回收器的類型
Serial收集器 (串行垃圾回收器)

image
image

  • 串行收集器是最古老、最穩定以及效率高的垃圾回收器。佈局

  • 使用單線程進行垃圾回收,獨佔式垃圾回收性能

  • 串行垃圾回收器經過持有應用程序全部的線程進行工做。它爲單線程環境設計,只使用一個單獨的線程進行垃圾回收,經過凍結全部應用程序線程進行工做,因此可能不適合服務器環境spa

  • 它最適合的是簡單的命令行程序(單CPU、新生代空間較小及對暫停時間要求不是很是高的應用)。是client級別默認的GC方式。命令行

  • 新生代、老年代使用串行回收;新生代複製算法、老年代標記-壓縮;垃圾收集的過程當中會Stop The World(服務暫停)

    參數控制: -XX:+UseSerialGC 串行收集器

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

image

image

  • ParNew收集器其實就是Serial收集器的多線程版本。新生代並行,老年代串行;新生代複製算法、老年代標記-壓縮

  • 只有他能與CMS收集器配合工做。

  • 參數控制:

    -XX:+UseParNewGC ParNew收集器 -XX:ParallelGCThreads 限制線程數量 -XX:+UseParNewGC:新生代使用並行收集器,老年代使用串行回收器。 -XX:+UseConcMarkSweepGC:新生代使用並行回收器,老年代使用CMS

  • 並行收集器工做時的線程數量可使用 -XX:ParallelGCThreads 參數指定。通常最好與CPU數量至關,避免過多的線程數,影響垃圾收集性能

  • 在默認狀況下,當CPU數量小於8個時,ParallelGCThreads 的值等於 CPU 數量;當 CPU 數量大於8個時,ParallelGCThreads 的值等於 3+[(5*CPU_Count)/8]

Parallel Scavenge 收集器 (並行垃圾回收器)
  • 並行垃圾回收器也被稱之爲:吞吐量收集器(throughput collector)

  • 他是jvm默認的垃圾回收器

  • 與串行垃圾回收器不一樣的是它使用多線程進行垃圾回收,使用的是複製算法

  • 類似的是執行垃圾回收的時候,他也會凍結全部的應用程序線程

  • 使用與CPU、對暫停時間要求較短的應用上,是server級別默認採用的GC方式。

  • 參數控制

    -XX:+UseParallelGC 新生代使用並行回收收集器,老年代使用串行回收器。 -XX:ParallelGCThreads=4 指定線程數

Parallel Old 收集器並行垃圾回收器)

image

  • Parallel Old是Parallel Scavenge收集器的老年代版本,使用多線程和「標記-整理」算法。這個收集器是在JDK 1.6中才開始提供

  • 參數控制

    -XX:+UseParallelOldGC 使用Parallel收集器+ 老年代並行

併發標記掃描垃圾回收器
  • 使用多線程掃描內存,標記須要清理的實例,而且清理已經標記的實例。
  • 併發標記掃描垃圾回收器只會在如下兩種狀況持有應用程序的全部線程
    • 標記的引用對象在永久(Tenured)區域
    • 在進行垃圾回收的時候,堆內存的數據被併發的改變。

相比並行垃圾回收器,併發標記掃描垃圾回收器使用更多的CPU來確保程序的吞吐量。若是咱們能夠爲了更好的程序性能分配更多的CPU,那麼併發標記上掃描垃圾回收器是更好的選擇相比並發垃圾回收器。

經過JVM參數 XX:+USeParNewGC 打開併發標記掃描垃圾回收器。

CMS收集器

image

  • CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間爲目標的收集器
  • 從名字(包含「Mark Sweep」)上就能夠看出CMS收集器是基於「標記-清除」算法實現的
  • 它的運做過程相對於前面幾種收集器來講要更復雜一些,整個過程分爲4個步驟,包括:
    • 初始標記(CMS initial mark)
    • 併發標記(CMS concurrent mark)
    • 從新標記(CMS remark)
    • 併發清除(CMS concurrent sweep)
  • 其中初始標記、從新標記這兩個步驟仍然須要「Stop The World」
  • 初始標記僅僅只是標記一下GC Roots能直接關聯到的對象,速度很快,
  • 併發標記階段就是進行GC Roots Tracing的過程
  • 從新標記階段則是爲了修正併發標記期間,因用戶程序繼續運做而致使標記產生變更的那一部分對象的標記記錄,這個階段的停頓時間通常會比初始標記階段稍長一些,但遠比並發標記的時間短
  • 因爲整個過程當中耗時最長的併發標記和併發清除過程當中,收集器線程均可以與用戶線程一塊兒工做,因此整體上來講,CMS收集器的內存回收過程是與用戶線程一塊兒併發地執行。老年代收集器(新生代使用ParNew)
優勢:

併發收集、低停頓

缺點:

產生大量空間碎片、併發階段會下降吞吐量

參數控制:
  1. -XX:+UseConcMarkSweepGC 使用CMS收集器
  2. -XX:+ UseCMSCompactAtFullCollection Full GC後,進行一次碎片整理;整理過程是獨佔的,會引發停頓時間變長
  3. -XX:+CMSFullGCsBeforeCompaction 設置進行幾回Full GC後,進行一次碎片整理
  4. -XX:ParallelCMSThreads 設定CMS的線程數量(通常狀況約等於可用CPU數量)
G1收集器
  • G1是目前技術發展的最前沿成果之一,HotSpot開發團隊賦予它的使命是將來能夠替換掉JDK1.5中發佈的CMS收集器
  • 空間整合,G1收集器採用標記整理算法,不會產生內存空間碎片。分配大對象時不會由於沒法找到連續空間而提早觸發下一次GC。
  • 可預測停頓,這是G1的另外一大優點,下降停頓時間是G1和CMS的共同關注點,但G1除了追求低停頓外,還能創建可預測的停頓時間模型,能讓使用者明確指定在一個長度爲N毫秒的時間片斷內,消耗在垃圾收集上的時間不得超過N毫秒,這幾乎已是實時Java(RTSJ)的垃圾收集器的特徵了。
  • 使用G1收集器時,Java堆的內存佈局與其餘收集器有很大差異,它將整個Java堆劃分爲多個大小相等的獨立區域(Region),雖然還保留有新生代和老年代的概念,但新生代和老年代再也不是物理隔閡了,它們都是一部分(能夠不連續)Region的集合。
以上的垃圾回收器須要組合使用

image

經常使用的收集器組合
組合 新生代GC策略 老年老代GC策略 說明
組合1 Serial Serial Old Serial和Serial Old都是單線程進行GC,特色就是GC時暫停全部應用線程。
組合2 Serial CMS+Serial Old CMS(Concurrent Mark Sweep)是併發GC,實現GC線程和應用線程併發工做,不須要暫停全部應用線程。另外,當CMS進行GC失敗時,會自動使用Serial Old策略進行GC
組合3 ParNew CMS 使用 -XX:+UseParNewGC選項來開啓。ParNew是Serial的並行版本,能夠指定GC線程數,默認GC線程數爲CPU的數量。可使用-XX:ParallelGCThreads選項指定GC的線程數。若是指定了選項 -XX:+UseConcMarkSweepGC選項,則新生代默認使用ParNew GC策略。
組合4 ParNew Serial Old 使用 -XX:+UseParNewGC選項來開啓。新生代使用ParNew GC策略,年老代默認使用Serial Old GC策略。
組合5 Parallel Scavenge Serial Old Parallel Scavenge策略主要是關注一個可控的吞吐量:應用程序運行時間 / (應用程序運行時間 + GC時間),可見這會使得CPU的利用率儘量的高,適用於後臺持久運行的應用程序,而不適用於交互較多的應用程序。
組合6 Parallel Scavenge Parallel Old Parallel Old是Serial Old的並行版本
組合7 G1GC G1GC -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC #開啓; -XX:MaxGCPauseMillis=50 #暫停時間目標; -XX:GCPauseIntervalMillis=200 #暫停間隔目標; -XX:+G1YoungGenSize=512m #年輕代大小; -XX:SurvivorRatio=6 #倖存區比例
相關文章
相關標籤/搜索