04-jvm-GC算法-算法理論

垃圾收集算法

標記-清除算法

image

  • 標記清除算法是最基礎的收集算法,爲了解決引用計數法的問題而提出的,他使用了根集的概念,
  • 分爲「標記」和「清除」兩個階段:首先標記出所須要回收的對象,在標記完成後,統一回收掉全部被標記的對象,它的標記過程其實就是前面的跟搜索算法中判斷垃圾對象的標記過程
  • 之因此說它是最基礎的收集算法,是由於後續的收集算法都是基於這種思路並對其缺點進行改進而獲得的 。
    image
優勢:
  • 不須要進行對象的移動,而且僅對不存活的對象進行處理,在存活對象比較多的狀況下極爲高效
缺點
  • 標記和清除的過程效率都不高:這種方法須要使用一個空閒列表來記錄全部的空閒區域及大小
  • 標記清除後,會產生大量不連續的內存碎片:雖然空閒區域的大小是足夠的,但卻可能沒有一個單一區域可以知足此次分配所需的大小,所以本次分配仍是會失敗(在Java中就是一次OutOfMemoryError)不得不觸發另外一次垃圾收集動做
標記-整理算法 又稱之:標記-壓縮算法

image

  • 該算法標記過程與標記-清除算法中的標記過程一致,可是對標記過程後的垃圾對象處理狀況不一樣
  • 它不是直接對可回收對象進行清理,而是讓全部的對象都向一端移動,而後清除掉端邊界之外的內存
  • 在基於標記-整理算法的收集器的實現中,通常增長句柄和句柄表
    image
優勢
  • 通過整理後,新對象分配只須要經過指針碰撞便能完成
  • 使用這種方法空閒區域的位置始終是可知的,也不會再由碎片的問題
缺點
  • GC的暫停時間會加長,由於須要將全部的對象都拷貝到一個新的地方去,還得更新他們的引用地址
複製算法

image

  • 該算法的提出是爲了解決句柄的開銷和堆碎片的垃圾回收
  • 他將內存按照容量分爲大小相等的兩塊,每次只使用其中一塊(對象面),當這一塊的內存用完了,就將該快還存活的對象複製到另外一塊的內存上面(空閒面),而後再把已經使用過的內存空間清理掉
  • 複製算法比較適合新生代,在老年代中,對象存活率比較高,若是執行較多的複製操做,效率將會下降,因此老年代通常會選用其餘的算法,如:標記-整理算法
  • 如今的商業虛擬機都採用這種收集算法來回收新生代,可是並非將新生代劃分爲大小相等的兩塊,而是分爲一塊較大的 Eden 空間和兩塊較小的 Survivor 空間,每次使用 Eden 空間和其中一塊 Survivor。在回收時,將 Eden 和 Survivor 中還存活着的對象一次性複製到另外一塊 Survivor 空間上,最後清理 Eden 和使用過的那一塊 Survivor。
  • HotSpot 虛擬機的 Eden 和 Survivor 的大小比例默認爲 8:1,保證了內存的利用率達到 90%。若是每次回收有多於 10% 的對象存活,那麼一塊 Survivor 空間就不夠用了,此時須要依賴於老年代進行分配擔保,也就是借用老年代的空間存儲放不下的對象

image

優勢
  • 標記階段和複製階段能夠同時進行
  • 每次只對一塊內存進行回收,運行高效
  • 只須要必定棧頂指針,按照順序分配內存便可,實現簡單
  • 內存回收的時候,沒必要考慮內存碎片
缺點
  • 須要一塊能容納下全部存活對象的額外內存空間,所以,可一次性分配的最大內存縮小了一半
分代收集
  • GC分代的基本假設:絕大部分對象的生命週期都很是短暫,存活時間短。算法

  • 「分代收集」(Generational Collection)算法,把Java堆分爲新生代和老年代,這樣就能夠根據各個年代的特色採用最適當的收集算法指針

  • 在新生代中,每次垃圾收集時都發現有大批對象死去,只有少許存活,那就選用複製算法,只須要付出少許存活對象的複製成本就能夠完成收集orm

  • 老年代中由於對象存活率高、沒有額外空間對它進行分配擔保,就必須使用「標記-清理」或「標記-整理」算法來進行回收。cdn

    若是說收集算法是內存回收的方法論,垃圾收集器就是內存回收的具體實現對象

相關文章
相關標籤/搜索