JVM(三)-- 垃圾回收

一:風騷概述

JVM中垃圾收集算法主要有複製算法、標記–清除、標記–整理、分代收集,每種垃圾收集器可以說都是一種或多種垃圾收集算法的實現。堆空間分代、垃圾收集器、垃圾收集算法三者的關係可以用以下特點概括:

  • 堆空間:不同對象根據存活時間內存大小等特點分佈在堆不同空間
  • 收集算法:不同堆空間對象回收率等存在明顯差異,選用不同特點垃圾收集算法
  • 收集器:收集算法實例即垃圾收集器

二:回收算法

不同垃圾收集算法具備不同的特點,對於每塊堆內存空間來講都有比較符合存儲對象特點的垃圾收集算法。主要介紹複製算法、標記 – 清除、標記 – 整理、分代收集算法

2.1 複製算法

在這裏插入圖片描述

  • 實現原理:將所有存活對象複製一份放入一塊內存,然後將區域外所有內存回收
  • 適用區域:堆空間新生代對象朝生夕死,存活對象比例低
  • 算法缺點:需要使用一塊內存區域作爲複製對象存放區域,內存使用率低
  • 新生代優化:新生代朝生夕死存活率低,將內存默認分爲8:1:1,默認使用1/10的S區域存放,避免大量內存浪費。同時使用分配擔保策略減少OOM風險
2.2 標記 – 清除算法

在這裏插入圖片描述

  • 實現原理:標記所有可回收對象將其進行回收
  • 適用區域:只有CMS收集器採用這個算法收集老年代
  • 算法缺點:容易造成內存碎片導致對象尋找不到合適內存從而誘發GC
  • 算法優點:實現簡單,不需要挪動存活對象位置,在對象存活率較高場景下比較優秀
2.3 標記 – 整理算法

在這裏插入圖片描述

  • 實現原理:標記可回收對象、將存活對象移動到連續內存區域、回收區域外內存
  • 適用區域:大部分老年代收集器採用算法
  • 算法缺點:在標記 – 清除算法基礎上增加對象挪動所以成本更高
  • 算法優點:相對於標記 – 清除解決了碎片內存問題,相對於複製算法避免了預留區域的問題。一定注意該算法是先標記 --> 再移動整合 --> 最後收集這個時間操作軸
2.4 分代收集算法

這塊內容留到G1垃圾收集器再專門介紹,簡單理解就是收集器根據不同內存區域採用不同算法實現垃圾回收

三:垃圾收集器

在這裏插入圖片描述
根據不同垃圾收集算法實現的垃圾收集器具備不同特點,當然也就運用於不同內存區域。其中新生代垃圾收集器包括Serial、ParNew、Parallel Scavenge,老年代垃圾收集器Serial Old、Parallel Old、CMS以及分代收集器G1等。不同的垃圾收集器可以配合使用,根據不同的需求場景可以選擇最合適的配合

3.1 Serial / Serial Old

在這裏插入圖片描述

  • Serial採用複製算法的新生代單線程垃圾收集器
  • Serial可配合老年代Serial Old、CMS進行垃圾收集
  • Serial是Client模式下默認垃圾收集器
  • Serial Old是Serial老年代實現採用標記 – 整理算法,除了可以配合所有新生代垃圾收集器外還可以作爲CMS的後備垃圾收集器
3.2 ParNew

在這裏插入圖片描述

  • 採用複製算法的新生代並行垃圾收集器,可看做爲Serial的多線程版本
  • 可配合Serial Old、CMS進行垃圾回收工作
3.3 Parallel Scavenge / Parallel Old

在這裏插入圖片描述

  • 採用複製算法的新生代並行收集器,關注吞吐量。即垃圾收集與線程運行時間比例
  • 可配合Serial Old、Parallel Old實現垃圾回收,與Parallel Old組成一組吞吐量優先的垃圾收集器
  • 吞吐量設定參數-XX:MaxGCPauseMillis指定垃圾收集最大停頓毫秒數時間、參數-XX:GCTimeRatio指定GC線程與用戶線程運行時間所佔最大比例
  • 與ParNew最大的一個區別在於自適應策略,參數-XX:+UseAdaptiveSizePolicy打開。自適應解釋爲虛擬機控制新生代、老年代大小比例以及Eden、From、To區域比例
  • Parallel Old是Parallel Scavenge的老年代版本實現,採用標記 – 整理算法。一組關注吞吐量的垃圾回收器
3.4 CMS

在這裏插入圖片描述

  • 垃圾收集劃分爲四個階段,初始標記 --> 併發標記 --> 重新標記 --> 併發清除。初始標記僅僅標記GCRoot節點、重新標記僅僅修正併發標記階段用戶線程運行導致的對象關係變化。所以整體上來看CMS在這兩個階段雖然有STW但是影響不大,可以稱得上併發收集器
  • CMS採用標記 – 清除垃圾回收算法,導致回收後產生大量內存碎片,可能會導致頻繁的發生GC
  • CMS是一款併發的垃圾收集器,也就是用戶線程還在持續運行。垃圾收集不能等到內存空間100%使用再進行,需要預留部分內存供用戶線程使用
  • 當併發進行的GC線程回收速度跟不上用戶線程垃圾產生速度,這時就會提示Concurrent Mode Failure從而啓動後備垃圾收集器Serial Old進行STW的垃圾回收
    在這裏插入圖片描述
3.5 G1

在這裏插入圖片描述

  • 首先需要明確G1垃圾收集器內存劃分採用化整爲零思想,一個個獨立的Regin區域組成整個GC堆。新生代、老年代概念僅僅標識某些可以物理上不連續的Regin集合
    在這裏插入圖片描述

  • G1收集器還有一個比較重要的特徵就是可預測停頓,這點與關注吞吐量的Parallel收集器類似。即在M時間段內可設置用戶垃圾回收的時長不超過N,具體實現原理就是將所有Region的垃圾收集維護一個優先級表,GC時計算出N時長內效率最高的一些Region進行回收

  • 當某個對象位於Region1,引用該對象的對象位於Region2,那麼在可達性算法分析時進行全堆掃描?G1中爲每個Region維護一個Remembered Set,當其它引用對象對該某個對象對象產生引用關係時就會在引用對象的Remembered Set中記錄,保證了引用關係標記的準確性

  • 除了初始標記與併發標記與CMS一致外,G1後兩個階段爲最終標記與篩選回收。篩選回收也就是根據上面講的優先級列表進行,該階段會STW並行執行,且回收算法帶有內存整合。最終標記就是將在併發標記階段用戶線程記錄到Remembered Set logs的引用關係合併到Remembered Set中,修正標記結果

四:垃圾收集參數

垃圾收集器具備多種搭配,每種垃圾收集器又都有一些自己獨特的配置。所以針對這兩點,將從垃圾收集器選擇參數以及收集器配置兩方面講解一些常用參數

4.1 Serial + SerialOld

這套垃圾收集器組合是Client模式下默認的垃圾收集器配置,若在Server模式下想強制指定該配置則使用參數-XX:+UseSerialGC即可。使用該組合垃圾收集器後新生代用DefNew 表示,老年代使用Tenured表示
在這裏插入圖片描述

4.2 ParNew + Serial Old

相對於Serial來講ParNew基本可以說是多線程版本,同時它還是出了Serial之外唯一可以與CMS合作的新生代垃圾收集器。使用參數-XX:UseParNew強制指定,使用ParNew垃圾收集器後新生代使用ParNew標記
在這裏插入圖片描述

4.3 Parallel Scavenge + Parallel Old

關注吞吐量,JDK1.8默認的垃圾收集器組合。使用參數+XX:UseParallelGC強制指定,前面講過相對於ParNew來講,Parallel Scavenge還有最重要的特徵就是堆內存分配自適應調節策略,使用參數-XX:UseAdaptiveSizePolicy參數打開。只需要設置最大最小堆,新生代老年代大小比例,新生代Eden、S區域比例,晉升老年代年齡等參數都會自動設置。這套組合的新生代用PSYoungGen、老年代用ParOldGen表示。當然吞吐量相關參數:

  • -XX:GCTimeRatio:0-100的整數,1 / (1 + GCTimeRatio) = 垃圾回收時間佔比
  • -XX:MaxGCPauseMillis : GC使用最長時間,單位毫秒
    在這裏插入圖片描述
4.4 ParNew + CMS + Serial

使用參數-XX:+UseConcMarkSweepGC強制指定垃圾收集器,需要注意的是這裏的Serial僅僅只是一個後備的垃圾收集器而已。當然使用CMS後老年代使用CMS表示,比較重要的一點就是CMS採用標記 – 清除算法有可能會導致重複頻繁的GC。爲了控制這種情況,CMS提供參數-XX:CMSFullGCsBeforeCompaction指定多少次Full GC後進行一次內存整理
在這裏插入圖片描述

五:GC發生時間

講完GC大部分相關內容後總得清楚什麼時候發生GC這個操作呀,首先需要明確的是GC分爲新生代的Minor GC 以及 老年代的Full GC。那麼這兩種GC到底在什麼時候觸發呢?

5.1 Minor GC

當新生代剩餘連續內存不足以分配新生對象,老年代剩餘空間滿足分配擔保策略需求的時候會執行Minor GC,如若不然執行Full GC
在這裏插入圖片描述

5.2 Full GC

除了上述說的因爲Minor GC引發的Full GC之外,還有什麼情況會導致Full GC的發生?如下所示:

  1. 顯示調用System.gc(),一般不會做這麼蠢的操作
  2. 大對象直接晉入老年代導致的老年代內存不足
  3. 方法區內存不足導致需要進行類卸載的GC
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章