天天看點

JVM筆記05.Garbage Collection

本文主要基于周志明老師的《深入了解Java虛拟機》。

文章目錄

    • Garbage Collection
      • 哪些記憶體需要被回收?
        • 引用計數算法 Reference Count
        • 可達性分析算法 Root Searching
        • 三色标記清除算法 Tri-color Marking
          • 增量更新 Incremental Update
          • 原始快照 Snapshot At The Beginning
      • 垃圾回收算法
        • 标記清除 Mark-Sweep
        • 拷貝 Copying
        • 标記壓縮 Mark-Compact
        • 标記-清除-壓縮 Mark-Sweep-Compat
      • 基于分代的垃圾回收
        • JVM記憶體分代模型
        • HotSpot中預設配置
        • MinorGc、MajorGC、YGC、FGC
        • 卡表 Card Table
      • 垃圾收集器
        • Serial
        • Serial Old
        • Parallel Old
        • Parallel Scavenge
        • ParNew
        • CMS
        • G1
        • Shenandoah
        • Epsilon
        • ZGC
        • JVM指定垃圾收集器
      • 拓展閱讀

Garbage Collection

  自Java引入垃圾回收以來,垃圾回收器的發展就未停止過。在JDK11種引入了ZGC,在JDK12種又引入了Shenandoah。雖然新的垃圾回收器不斷地湧現,但是垃圾回收的基礎算法變化并不大。簡單來說,回收算法主要有複制、标記清除、标記壓縮。

  垃圾回收可以分為三個問題:哪些記憶體需要被回收?什麼時候去回收?如何回收?

哪些記憶體需要被回收?

  簡單的說,沒有任何引用指向的一個對象或者循環引用的多個對象。需要被回收。目前垃圾回收算法主要有兩類,引用計數法和可達性分析算法。JVM的垃圾回收采用了可達性分析法。

引用計數算法 Reference Count

  在堆記憶體中配置設定對象時,會為對象配置設定一段額外空間。這段空間用于記錄引用計數,當對象增加了一個新的引用,則将增加計數器的值。如果一個引用關系失效,則減少計數器的值。當一個對象的計數器的值變成0,則說明該對象已經被廢棄,處于不活躍狀态,可以被回收。引用計數法存在無法回收循環引用的問題,并且并發計數需要上鎖效率低。Python語言中使用的便是引用計數法。

可達性分析算法 Root Searching

通過一組根對象根據引用鍊向下标記,沒有被标記到的對象被稱為不可達,證明此對象可被回收。

三色标記清除算法 Tri-color Marking

三色标記清除算法

https://www.bilibili.com/video/BV1KU4y1Y7cu

增量更新&SATB

https://www.bilibili.com/video/BV1Uz4y1S798

三色标記清除算法中用三種顔色來區分不同的記憶體節點。

  • 白 沒有周遊到的節點。
  • 灰 自己标記完成,還沒來得及标記子節點。
  • 黑 自己标記完成,子節點都标記完成。

并發标記導緻的"對象消失"問題,當且僅當以下兩個條件同時滿足時,會産生“對象消失”的問題,即原來應該是黑色的對象被誤标成了白色。

  • 指派器插入一條或多條從黑色對象到白色對象的新引用。
  • 指派器删除了全部從灰色對象到該白色對象的直接或間接引用。

對此分别有兩種解決方案,增量标記(Incremental Update)和原始快照(SATB)。

增量更新 Incremental Update

在JVM中,CMS采用的是增量标記。

增量更新破壞了第一個條件,可以簡化了解為把黑色重新标記為灰色,下次重新掃描子節點。

原始快照 Snapshot At The Beginning

在JVM中,G1采用原始快照。

原始快照破壞了第二個條件,可以簡化了解為無論引用關系删除與否,都會按照剛開始掃描那一刻的對象圖快照來進行搜尋。

垃圾回收算法

标記清除 Mark-Sweep

JVM筆記05.Garbage Collection

标記清除

位置不連續 産生碎片 效率偏低(兩遍掃描)

拷貝 Copying

JVM筆記05.Garbage Collection

拷貝

沒有碎片,浪費空間

标記壓縮 Mark-Compact

JVM筆記05.Garbage Collection

标記壓縮

沒有碎片,效率偏低(兩遍掃描,指針需要調整)

标記-清除-壓縮 Mark-Sweep-Compat

多次GC後才壓縮,是标記清除和标記壓縮的結合。

基于分代的垃圾回收

基于分代的垃圾回收的本質就是分代假說。弱分代假說(weak generational hypothesis)的含義是:大多數對象都在年輕時死亡。強分代假說(strong generational hypothesis)的含義是:越老的對象越不容易死亡。

更多内容請參考《垃圾回收算法手冊:自動記憶體管理的藝術》。

JVM記憶體分代模型

JVM筆記05.Garbage Collection

HotSpot虛拟機的垃圾收集器

除Epsilon、ZGC、Shenandoah之外的垃圾收集器都是使用邏輯分代模型。G1采用邏輯分代實體不分代,是以可以同時用于傳統意義上的年輕代和老年代。除此之外的垃圾收集器不僅邏輯分代還實體分代。

HotSpot中預設配置

新生代 :老年代 = 1 : 3

新生代 = Eden + Suvivor0 + Suvivor1

Eden :Suvivor0 :Suvivor1 = 8 :1 :1

MinorGc、MajorGC、YGC、FGC

YGC = Young GC = MinorGC

FGC = Full GC = MajorGC

卡表 Card Table

垃圾回收跨代引用/卡表/寫屏障

https://www.bilibili.com/video/BV1Jy4y1p7t8

執行YGC時,需要掃描整個老年代,效率非常低,是以JVM設計了CardTable。如果一個老年代CardTable中有對象指向年輕代,就将它設為Dirty,下次掃描時,隻需要掃描Dirty Card。

在資料結構上,Card Table用BitMap來實作。

垃圾收集器

Serial

Serial是一個stop-the-world,基于拷貝算法的單GC線程年輕代垃圾收集器。

Serial Old

Serial Old是一個stop-the-world,基于mark-sweep-compact(MSC)算法的單GC線程老年代垃圾收集器。

Parallel Old

Parallel Old是一個stop-the-world,基于壓縮算法的多GC線程老年代垃圾收集器。

Parallel Scavenge

Paralledl Scavenge是一個stop-the-world,基于拷貝算法的多GC線程年輕代垃圾收集器。

ParNew

在ParNew在Paralledl Scavenge之後誕生,是以叫Parallel New。

Parallel Old是一個stop-the-world,基于壓縮算法的多GC線程老年代垃圾收集器。

他和Paralledl Scavenge的差別是它做了增強使他可以和CMS配合使用。

CMS

Concurrent Mark Sweep

算法:三色标記 + Incremental Update

老年代

垃圾回收和應用程式同時運作,降低STW的時間(200ms)

CMS問題比較多,是以現在沒有一個版本預設是CMS,隻能手工指定

一個大多數并發、低停頓的收集器

CMS既然是MarkSweep,就一定會有碎片化的問題,碎片到達一定程度,CMS的老年代配置設定對象配置設定不下的時候,使用SerialOld 進行老年代回收

4階段

初始标記 initial mark (STW)

并發标記 concurrent mark

重新标記 remark (STW)

并發清除 concurrent sweep

G1

算法:三色标記 + SATB(Snapshot-At-The-Beginnin)

Shenandoah

算法:ColoredPointers + WriteBarrier

Epsilon

Epsilon不回收記憶體,用來做測試的。

ZGC

算法:ColoredPointers + LoadBarrier

JVM指定垃圾收集器

-XX:+UseSerialGC = Serial New (DefNew) + Serial Old  

-XX:+UseParNewGC = ParNew + SerialOld(某些版本已廢棄)

-XX:+UseConcMarkSweepGC = ParNew + CMS + Serial Old  

-XX:+UseParallelGC = Parallel Scavenge + Parallel Old (1.8預設)

-XX:+UseParallelOldGC = Parallel Scavenge + Parallel Old  

-XX:+UseG1GC = G1
           

拓展閱讀

《垃圾回收算法手冊:自動記憶體管理的藝術》.https://book.douban.com/subject/26740958

《新一代垃圾回收器ZGC設計與實作》.https://book.douban.com/subject/34812818/