幾種垃圾回收算法

垃圾回收GC的全拼是 Garbage Collection 其在維基百科的定義是: 在計算機科學(xué)中,垃圾回收(英語:Garbage Collection,縮寫為GC)是一種自動的內(nèi)存管理機制。當(dāng)一個電腦上的動態(tài)內(nèi)存不再需要時,就應(yīng)該予以釋放,以讓出內(nèi)存,這種內(nèi)存資源管理,稱為垃圾回收(garbage collection)

垃圾回收算法有多種,先看看幾個評價垃圾回收算法性能的幾個方面,再具體看看各種算法的優(yōu)缺點

  • 吞吐量 throughput
  • 最大暫停時間
  • 堆使用效率
  • 訪問的局部性

一、 標(biāo)記-清除算法 Mark-Sweep GC

如字面意思 mark-sweep 分為兩個階段:

  1. 標(biāo)記階段:從根集合出發(fā),將所有活動對象及其子對象打上標(biāo)記
  2. 清除階段:遍歷堆,將非活動對象(未打上標(biāo)記)的連接到空閑鏈表上


    標(biāo)記-清除算法

優(yōu)點

實現(xiàn)簡單, 容易和其他算法組合

缺點

  • 碎片化, 會導(dǎo)致無數(shù)小分塊散落在堆的各處
  • 分配速度不理想,每次分配都需要遍歷空閑列表找到足夠大的分塊
  • 與寫時復(fù)制技術(shù)不兼容,因為每次都會在活動對象上打上標(biāo)記

二、標(biāo)記-壓縮 Mark-Compact

和“標(biāo)記-清除”相似,不過在標(biāo)記階段后它將所有活動對象緊密的排在堆的一側(cè)(壓縮),消除了內(nèi)存碎片, 不過壓縮是需要花費計算成本的。如下圖過程,標(biāo)記后需要定位各個活動對象的新內(nèi)存地址,然后再移動對象,總共搜索了3次堆。


標(biāo)記-壓縮算法

優(yōu)點

有效利用了堆,不會出現(xiàn)內(nèi)存碎片 也不會像復(fù)制算法那樣只能利用堆的一部分

缺點

壓縮過程的開銷,需要多次搜索堆

三、引用計數(shù) Reference Counting

引用計數(shù),就是記錄每個對象被引用的次數(shù),每次新建對象、賦值引用和刪除引用的同時更新計數(shù)器,如果計數(shù)器值為0則直接回收內(nèi)存。 很明顯,引用計數(shù)最大的優(yōu)勢是暫停時間短

優(yōu)點

  • 可即刻回收垃圾
  • 最大暫停時間短
  • 沒有必要沿指針查找, 不要和標(biāo)記-清除算法一樣沿著根集合開始查找

缺點

  • 計數(shù)器的增減處理繁重
  • 計數(shù)器需要占用很多位
  • 實現(xiàn)繁瑣復(fù)雜, 每個賦值操作都得替換成引用更新操作
  • 循環(huán)引用無法回收

四、 GC 復(fù)制算法

將堆分為兩個大小相同的空間 From 和 To, 利用 From 空間進行分配,當(dāng) From 空間滿的時候,GC將其中的活動對象復(fù)制到 To 空間,之后將兩個空間互換即完成GC。


GC復(fù)制算法

優(yōu)點

  • 優(yōu)秀的吞吐量, 只需要關(guān)心活動對象
  • 可實現(xiàn)高速分配; 因為分塊是連續(xù)的,不需要使用空閑鏈表
  • 不會發(fā)生碎片化
  • 與緩存兼容

缺點

  • 堆使用率低
  • 與保守式GC不兼容
  • 遞歸調(diào)用函數(shù), 復(fù)制子對象需要遞歸調(diào)用復(fù)制函數(shù) 消耗棧

五、 保守式GC

根空間有以下幾種:

  • 寄存器
  • 調(diào)用棧
  • 全局變量空間

但這些都是不明確的根, 因為調(diào)用棧里邊的調(diào)用幀(call frame) 既有指針也有非指針(值類型)

保守式GC檢查不明確根的基本項目:

  1. 是不是被正確對齊的值?(在32位cpu的情況下,為4的倍數(shù))
  2. 是不是指針堆內(nèi)?
  3. 是不是指著對象的開頭?

有種情況是,非指正和堆里的對象地址一樣;這時保守式GC “把可以的東西看做指針,穩(wěn)妥處理”

保守式GC優(yōu)點:GC不依賴于語言處理程序

缺點:

  • 識別指針和非指針需要成本
  • 錯誤識別指針會壓迫堆; 可能錯將非指針當(dāng)做指針,然后將其作為內(nèi)存地址使得對應(yīng)堆中的死對象當(dāng)做活對象
  • 能夠使用的gc算法有限; 不能使用復(fù)制算法這類移動對象的gc算法
準(zhǔn)確式GC

需要依賴 “語言處理程序的支援”,能基于能精確識別指針和非指針的“正確根”來執(zhí)行g(shù)c

六、分代回收

出發(fā)點:大部分對象生成后馬上就變成垃圾,很少有對象能活的很久

  • 新生代 = 生成空間 + 2 * 幸存區(qū) 復(fù)制算法
  • 老年代 標(biāo)記-清除算法

對象在生成空間創(chuàng)建,當(dāng)生成空間滿之后進行 minor gc,將活動對象復(fù)制到第一個幸存區(qū),并增加其“年齡” age,當(dāng)這個幸存區(qū)滿之后再將此次生成空間和這個幸存區(qū)的活動對象復(fù)制到另一個幸存區(qū),如此反復(fù),當(dāng)活動對象的 age 達到一定次數(shù)后將其移動到老年代; 當(dāng)老年代滿的時候就用標(biāo)記-清除或標(biāo)記-壓縮算法進行major gc

吞吐量得到改善, 分代垃圾回收花費的時間是GC復(fù)制算法的四分之一;但是如果部分程序新生成對象存活很久的話分代回收會適得其反

七、增量式GC

本來gc只是默默的在幕后回收資源的,但是如果gc任務(wù)繁重則會長時間暫停應(yīng)用程序的執(zhí)行, 增量式gc就是一種逐漸推進垃圾回收來控制mutator最大暫停時間的方法

三色標(biāo)記算法

  • 白色: 還未搜索過的對象
  • 灰色: 正在搜索的對象
  • 黑色: 搜索完成的對象

根查找階段: 對能直接從根引用的對象打上標(biāo)記,堆放到標(biāo)記棧里(白色 涂成 灰色)

標(biāo)記階段: 從標(biāo)記棧中取出對象,將其子對象涂成灰色;這個階段不是一下子處理所有的灰色對象,而只是處理一定個數(shù),然后暫停gc

清除階段: 將沒被標(biāo)記的白色對象連接到空閑鏈表,并重置已標(biāo)記的對象標(biāo)記位

優(yōu)點: 縮短最大暫停時間
缺點: 降低了吞吐量

resources:
維基百科 - 垃圾回收
深入理解java垃圾回收機制
聊聊JVM的年輕代

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容