【jvm】垃圾收集器

在瞭解垃圾收集算法以後,咱們要看一下基於垃圾收集算法實現的垃圾收集器是如何實現的,本文出現的垃圾收集器都是HotSpot虛擬機提供的實現html

堆內存是垃圾收集器主要回收垃圾對象的地方,堆內存能夠根據對象生命週期的不一樣細分爲新生代和老年代,每一個年代均可以選擇適合的垃圾收集算法,新生代使用複製算法,老年代使用標記清除或者標記整理算法java

HotSpot虛擬機提供了7種垃圾收集器,其中適用於新生代的三種,老年代的三種,還有一種新生代老年代都適用算法

新生代垃圾收集器:Serial收集器,ParNew收集器,Parallel Scavenge收集器多線程

老年代垃圾收集器:Serial Old收集器,Parallel Old收集器,CMS收集器併發

都適用的收集器:G1收集器jvm

全部垃圾收集器組合狀況以下:性能

圖中連線的收集器代表能夠一塊兒搭配使用線程

Serial 收集器

Serial收集器曾是jdk1.3以前新生代收集器的惟一選擇,串行收集器,單線程工做,因此效率高,可是會產生Stop The World,適用於堆內存比較小的時候使用,使用複製算法回收垃圾對象3d

參數設置:-XX:+UseSerialGC 使用Serial收集器cdn

ParNew 收集器

parNew收集器是Serial收集器的多線程版本,並行收集器,除了多線程收集外,其他功能與Serial收集器基本一致,在新生代中,除了Serial收集器,只有ParNew收集器能夠與CMS收集器一塊兒使用,因此目前爲止這個收集器是新生代最經常使用的收集器

參數設置:

  • -XX:+UseParNewGC:使用ParNew收集器
  • -XX:ParallelGCThreads:用來限制垃圾收集的線程數

Parallel Scavenge 收集器

並行收集器,一樣使用複製算法,與其他兩種年輕代收集器不一樣的地方在於它的關注點,Serial和ParNew收集器的關注點在於儘量的縮短Stop The World的時間,而Parallel Scavenge收集器的關注點在於吞吐量

吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間),好比虛擬機運行100分鐘,垃圾收集時間是1分鐘,那麼吞吐量就是99%

參數設置:

  • -XX:+UseParallelGC:使用Parallel收集器
  • -XX:MaxGCPauseMillis:控制最大垃圾收集停頓時間
  • -XX:GCTimeRatio:設置吞吐量大小,默認爲99,容許1%的垃圾收集時間
  • -XX:+UseAdaptiveSizePolicy:自適應調節,設置以後就不須要手動設置新生代大小

Serial Old 收集器

Serial Old收集器是Serial的老年代版本,單線程收集器,使用標記整理算法

能夠與Parallel Scavenge收集器搭配使用,也能夠做爲CMS收集器發生Concurrent Mode Failure時老年代的備選方案使用

Parallel Old 收集器

Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用標記整理算法

在注重吞吐量及CPU資源敏感的場景,能夠用考慮使用Parallel Scavenge+Parallel Old收集器

參數設置:-XX:+UseParallelOldGC:使用Parallel Scavenge + Parallel Old收集器

CMS收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間爲目標的收集器,目前使用最多的垃圾收集器,使用這類收集器的應用重視服務的響應速度,但願系統停頓時間最短,以給用戶帶來較好的體驗

使用標記清除算法,共4個步驟

  1. 初始標記(CMS initial mark)
  2. 併發標記(CMS concurrent mark)
  3. 從新標記(CMS remark)
  4. 併發清除(CMS concurrent sweep)

初始標記、從新標記這兩個步驟仍然須要Stop The World,初始標記僅僅只是標記一下GC Roots能直接關聯到的對象,速度很快,併發標記階段就是進行GC Roots Tracing的過程,而從新標記階段則是爲了修正併發標記期間,因用戶程序繼續運做而致使標記產生變更的那一部分對象的標記記錄,這個階段的停頓時間通常會比初始標記階段稍長一些,但遠比並發標記的時間短

耗時較長的併發標記和併發清除的線程能夠與用戶線程一塊兒工做,因此整體上來講,CMS收集器的內存回收過程是與用戶線程一塊兒併發地執行

優勢:併發收集,低停頓

缺點:

  1. 對CPU資源敏感

    CMS默認啓動的回收線程數量是(CPU數量+3)/4,當CPU數量小於4時,併發操做時會佔用一半的CPU去進行垃圾收集

  2. 沒法處理浮動垃圾,可能回致使Concurrent Mode Failure失敗而致使領一次Full GC的產生

    CMS收集器觸發GC時須要預留一部分空間供併發收集時使用,經過設置參數-XX:CMSInitiatingOccupancyFraction的值來提升觸發的百分比

    當預留的空間沒法知足需求時就會發生Concurrent Mode Failure失敗,這時,java虛擬機就會採用Serial Old收集器回收老年代垃圾,代價就是停頓時間變長

    因此-XX:CMSInitiatingOccupancyFraction參數設置的太高容易頻繁觸發Concurrent Mode Failure失敗,致使性能下降

  3. 產生大量空間碎片

    設置-XX:+ UseCMSCompactAtFullCollection參數,開啓空間壓碎,默認是開啓的,開啓後FUll GC時會進行內存整理,空間碎片問題解決,可是停頓時間就會變長

    設置-XX:+ CMSFullGCsBeforeCompaction參數,設置進行幾回Full GC後,進行一次碎片整理,默認是0,表示每次進入Full GC時都進行碎片整理

參數設置:

  • -XX:+UseConcMarkSweepGC:使用CMS收集器 + PerNew收集器
  • -XX:ParallelCMSThreads:設定CMS的線程數量

G1 收集器

G1是一款面向服務端應用的垃圾收集器,HotSpot開發團隊賦予它的使命是將來能夠替換掉JDK1.5中發佈的CMS收集器

G1收集器採用標記整理算法,因此G1收集器不會產生空間碎片

G1特色:

  • 並行與併發

    G1能夠充分的利用多CPU和多核環境下的硬件優點用來縮短Stop The World的停頓時間

  • 可預測的停頓

    下降停頓時間是G1和CMS的共同關注點,但G1除了追求低停頓外,還能創建可預測的停頓時間模型,能讓使用者明確指定在一個長度爲N毫秒的時間片斷內,消耗在垃圾收集上的時間不得超過N毫秒,這幾乎已是實時Java(RTSJ)的垃圾收集器的特徵了

G1收集器將整個Java堆劃分爲多個大小相等的獨立區域(Region),雖然還保留有新生代和老年代的概念,但新生代和老年代再也不是物理隔閡了,它們都是一部分(能夠不連續)Region的集合

G1的新生代收集跟ParNew相似,當新生代佔用達到必定比例的時候,開始出發收集;和CMS相似,G1收集器收集老年代對象會有短暫停頓

收集步驟:

  1. 初始標記

    標記一下GC Roots能直接關聯到的對象

  2. 併發標記

    從GC Roots出發,開始對堆中對象進行可達性分析,找出存活對象

  3. 最終標記

    爲了修正併發標記階段因用戶程序繼續運行而致使標記產生變更的那一部分標記記錄

  4. 篩選回收

    對各個Region的回收價值和成本進行排序,根據用戶所期待的GC停頓時間來制定回收計劃

參考: jvm系列(三):java GC算法 垃圾收集器

深刻理解java虛擬機第二版

更多閱讀:chenmingyu.top/categories/

相關文章
相關標籤/搜索