天天看點

Java - 垃圾回收算法與垃圾回收器

垃圾回收算法

1. 标記-清除

  • 過程:标記所有需要回收的對象,标記結束後,回收所有被标記的對象
  • 缺點:效率低下,容易造成碎片

2. 複制

  • 将記憶體空間分為兩部分,每次隻使用一部分,當一部分用盡,則将其所有對象複制到另一部分,并清理自身
  • 特點:不産生碎片,但造成空間浪費
  • 老年代将記憶體分為一個Eden 和兩個Survivor,每次使用一個Eden 和一個Survivor,回收時,将存活的對象複制到另一個Survivor,當待複制對象大于另一個Survivor 時,老年代進行擔保

3. 标記-整理

  • 标記之後,将所有存活的對象移向另一端,清理其他對象
  • 優點:解決了對象存活率高時,複制對象的壓力

4. 分代收集

根據年輕代[ 1, 2]、老年代[ 3]各自的特點,采用不同回收算法

垃圾回收器

Serial

單線程,在進行GC 時,需要停止其他的所有線程

ParNew

Serial 的多線程版本。但是在單線程環境下,由于線程開銷較大,效果不如Serial。但随着CPU 的增加,便可以顯現出優勢,預設線程數等于 CPU數。

Parallel Scavenge

多線程。可設定 1. 吞吐量(cpu 運作100分鐘,GC 使用1分鐘,Throughput = 99%),2. 最大GC 停頓時間(縮小GC 停頓時間,要以犧牲吞吐量和增加GC 頻率為代價)

年輕代與老年代的分界線

Serial Old

Serial 的老年代版本

CMS

擷取最短GC 停頓時間。基于标記-清除算法。

  • 初始階段:主要負責标記GC Root能直接關聯的對象,速度快。
  • 并發标記:從GC Root 開始繼續向下标記,耗時。
  • 重新标記:統計在并發标記過程中發生變化的标記,時間長于 初始階段但小于 并發标記。
  • 并發清除:清除老年代中的垃圾,耗時。

缺點:

  • 産生碎片
  • 浮動垃圾
  • 對cpu 敏感

G1

可同時應用于年輕代和年老代的GC 器。基于标記-整理算法。使用時,堆記憶體布局發生變化,将堆分成性質不同的但大小相同的region,用以避免全局GC,建立可預測的停頓時間模型。每個 region對應一個 remembered set,當對象處于不同region,remember set 會進行記錄,即可保證不進行全局GC,也不會遺漏。

  • 初始标記
  • 并發标記
  • 最終标記:将并發标記過程中發生變化的對象寫入線程remember set log,同時與remembered set 合并
  • 篩選回收:通過比較region 的回收成本與價值,得到一個最好的回收方案

parallel old

老年代。标記-整理。吞吐量優先。

GC 時,程式邏輯是否繼續執行?

Serial、parnew 等=> stop the world

繼續閱讀