《垃圾回收的算法與實現》——分代垃圾回收

分代垃圾回收

  • 理論支持:經驗得出——"大部分的對象在生成後立刻就變成了垃圾,不多有對象能活得好久"。
  • 分代垃圾回收將剛生成的對象稱爲新生代,達到必定年齡(進過一次GC即一歲)的對象稱爲老年代,不一樣代的對象使用不一樣回收算法。
  • 新生代對象執行GC稱爲新生代GC(minor GC)。
  • 新生代對象存活必定次數GC將晉升到老年代,老年代的GC稱爲老年代GC(major GC)。

Ungar的分代垃圾回收

準備

  • 堆分爲生成空間(分配內存的位置)、2個大小相等的倖存空間(From和To)以及老年代空間。
  • 記錄集用於記錄老年代指向新生代的引用,爲了便於高效的尋找從老年代到新生代的引用。
  • 記錄集記錄的是老年代中發出引用的對象
  • 記錄集經過寫入屏障在mutator更新對象間的指針操做進行寫入。
  • 對象須要增長三個字段:
    • age:對象年齡
    • forwarded:已經複製完畢的標誌
    • remembered:已經向記錄集記錄完畢的標誌

分配

  • 分配是在生成空間進行,其分配算法與複製算法基本一致。
  • 當空間不夠將發起minor GC,若是還不足則表示生成空間比新對象小,這種有些直接寫入老年代。

新生代GC

  • minor GC把生成空間和From中的對象複製到To或老年代,具體複製目標由對象年齡決定。
  • 當對象須要晉升到老年代時,若是老年代空間不夠將發起一次major GC。
  • 晉升時不只要設置forwarded和forwaring,若是該對象還有引用了新生代的對象則須要寫入到記錄集。
  • minor GC的根除了正常的GC root還有記錄集中的對象。

老年代GC

老年代GC使用Mark-Sweep算法。html

總結

  • 改善了GC所花費的時間,提升了吞吐量。
  • 其針對的是「很對年輕代對象很快就死了」,若是不符合這個特色可能形成相反的結果。

記錄各代之間引用的方法

卡片標記

  • 將老年代按照必定大小分割,分割後的空間稱爲卡片,每一個卡片準備一個標誌位。
  • 優勢在於節約空間並且不會像記錄集那樣可能會溢出。
  • 缺點在於搜索標誌位。

頁面標記

  • 許多OS以頁面對內存進行管理,將卡片標記法的卡片大小設爲頁的大小。
  • 當某個頁進行寫入操做時,設置該頁的重寫標誌位,從而達到標記。
  • 缺點:並非全部OS都支持頁的模式。

改進

多代垃圾回收

  • 增長代數,給每代記錄一個記錄集。
  • 並非代數越多越好,須要根據實際狀況判斷。

列車垃圾回收

  • 目的在於控制老年代GC的最大停頓時間。
  • 堆劃分爲一個個車箱,1個以上的車箱鏈接構成列車,1次老年代GC是以1個車箱做爲GC對象。
  • 每一個車箱和每一個列車均有一個對應的記錄集,記錄來自其餘車箱或列車的引用。
  • 新生代GC將GC root和記錄集中引用的對象複製到老年代,其中GC root引用相關對象將複製到一個空閒車箱,而記錄集中的對象則複製到老年代發起引用的車箱對應列車的尾車箱中。
  • 老年代GC以列車開頭車箱做爲GC對象,將該車箱對象複製與年輕代複製的目標選擇同樣。
  • 寫入屏障,老年代指向新生代則寫入新生代記錄集,老年代指向老年代則若是指針目標對象所在的車箱在指針對象所作車箱以前須要記錄到指針目標對象的記錄集中(緣由在於按順序回收車箱)

轉載於:https://www.cnblogs.com/suolu/p/6660087.html算法