天天看點

深入了解Java虛拟機筆記(4)-------垃圾回收算法

分代收集理論的三條假說
  • 弱分代假說:絕大多數對象都是朝生夕滅的(大多數對象(大概98%)第一次垃圾回收時就被回收掉了)
  • 強分代假說:熬過越多次垃圾收集過程的對象就越難以消亡(eg:經過幾次垃圾回收都沒有被回收的對象,下一次回收很可能也不會回收它)
  • 跨代引用假說:跨代引用相對于同代引用來說僅占極少數(跨代引用就是新生代和老年代的對象之間有引用關系,有這種跨代引用的對象很少)

接下來主要說三種垃圾收集算法: 标記-清除算法,标記-複制算法,标記-整理算法。

1. 标記-清除算法:

該算法分為标記和清除兩個階段:根據垃圾回收判斷算法先标記出所有需要回收的對象,然後再回收他們;或者反過來标記所有不需要回收的對象,然後回收所有沒有标記的對象。

标記-清除算法明顯的缺點有兩個:

- 效率不穩定:如果記憶體中有大量需要回收的對象,那麼垃圾回收器就要做大量的标記-清除工作;也就是說算法的效率随需要回收對象的數量的增長而增長。

- 記憶體空間碎片化問題:如果需要回收的對象散落的分布在記憶體中,回收之後記憶體中會産生很多不連續的碎片,當再需要配置設定一塊較大的連續記憶體的時候就無法滿足,進而提早進行下一次的垃圾回收。

深入了解Java虛拟機筆記(4)-------垃圾回收算法

2. 标記-複制算法:

标記-複制算法将記憶體劃分為相等的兩塊,每次隻使用其中一塊。當一塊的記憶體空間不足的時候,就把所有存活的對象複制到另一塊記憶體中,然後把使用過的記憶體一次性都清理掉。這樣在一般情況下(弱分代假說)隻需要複制少數的存活對象,而且不會産生記憶體碎片。但是缺點也很明顯:可用的記憶體空間變成了一半。

深入了解Java虛拟機筆記(4)-------垃圾回收算法

HotSpot虛拟機的一些新生代垃圾收集器就采用這種算法,不過記憶體并不是五五開的,而是分為一個Eden和兩個Survivor(根據弱分代假說,配置設定比例為8:1:1),假設記憶體為10,就配置設定大小為8的Eden和兩個大小為1的Survivor,每次隻用Eden和其中一個Survivor1配置設定記憶體,當記憶體不足需要回收時,就把用過的Eden和Survivor1中的存活對象複制到Survivor2中,然後清除Eden和Survivor1,再用Eden和Survivor2配置設定記憶體。這也就是為什麼需要兩個Survivor的原因(隻有一個的話用來配置設定的記憶體和用來複制的記憶體的角色無法切換)。而為了應對存活的對象超過10%的情況,當Survivor空間不足以容納一次Minor GC(新生代垃圾回收)之後存活的對象時,就需要依賴其他記憶體區域(實際上大多就是老年代)進行配置設定擔保。

3. 标記-整理算法:

标記-整理算法大體上與标記-清除算法一樣,但是當标記完之後并不是直接回收死亡的對象,而是把所有存活的對象移動到記憶體的一端,然後回收邊界意外的所有記憶體。這種算法的缺點也較為明顯,就是移動對象需要額外的開銷

HotSpot虛拟機裡面關注吞吐量的ParallelScavenge收集器是基于标記-整理算法的,而關注延遲的CMS收集器則是基于标記-清除算法的。

深入了解Java虛拟機筆記(4)-------垃圾回收算法