Jvm垃圾回收器(算法篇)

  在《Jvm垃圾回收器(基礎篇)》中咱們主要學習了判斷對象是否存活仍是死亡?兩種基礎的垃圾回收算法:引用計數法、可達性分析算法。以及Java引用的4種分類:強引用、軟引用、弱引用、虛引用。和方法區的回收介紹。html

那麼接下來咱們重點研究下虛擬機的幾種常見的垃圾回收算法:標記-清除算法、複製算法、標記-整理算法、分代收集算法。java

一:標記-清除算法

  最基礎的收集算法,總共分爲‘ 標記 ’和‘ 清除 ’兩個階段算法

1.標記

  標記出全部須要回收的對象佈局

  在《Jvm垃圾回收器(基礎篇)》中說明了判斷對象是否回收須要兩次標記,如今咱們再來回顧一下post

  一次標記:在通過可達性分析算法後,對象沒有與GC Root相關的引用鏈,那麼則被第一次標記。而且進行一次篩選:當對象有必要執行finalize()方法時,則把該對象放入F-Queue隊列中。學習

  二次標記:對F-Queue隊列中的對象進行二次標記。在執行finalize()方法時,若是對象從新與GC Root引用鏈上的任意對象創建了關聯,則把他移除出「 即將回收 」集合。不然就等着被回收吧!!!url

  對被第一次標記切被第二次標記的,就能夠斷定位可回收對象了。spa

2.清除

  兩次標記後,還在「 即將回收 」集合的對象進行回收。.net

  執行過程以下:代理

  優勢:基礎最基礎的可達性算法,後續的收集算法都是基於這種思想實現的

  缺點:標記和清除效率不高,產生大量不連續的內存碎片,致使建立大對象時找不到連續的空間,不得不提早觸發另外一次的垃圾回收。

二:複製算法

  將可用內存按容量分爲大小相等的兩塊,每次只使用其中一塊,當這一塊的內存用完了,就將還存活的對象複製到另一塊內存上,而後再把已使用過的內存空間一次清理掉。

  複製算法執行過程以下:

  優勢:實現簡單,效率高。解決了標記-清除算法致使的內存碎片問題。

  缺點:代價太大,將內存縮小了一半。效率隨對象的存活率升高而下降。

 如今的商業虛擬機都採用這種算法(須要改良1:1的缺點)來回收新生代。

2.1 HotSpot虛擬機的改良算法 

1.弱代理論 

  分代垃圾收集基於弱代理論。具體描述以下:

  • 大多說分配了內存的對象並不會存活太長時間,在處於年輕時代就會死掉。
  • 不多有對象會從老年代變成年輕代。

   其中IBM研究代表:新生代中98%的對象都是"朝生夕死"; 因此並不須要按1:1比例來劃份內存(解決了缺點1);

 2.Hotspot虛擬機新生代內存佈局及算法

  新生代內存分配一塊較大的Eden空間和兩塊較小的Survivor空間

  每次使用Eden和其中一塊Survivor空間

  回收時將Eden和Survivor空間中存活的對象一次性複製到另外一塊Survivor空間上

  最後清理掉Eden和使用過的Survivor空間。

Hotspot虛擬機默認Eden和Survivor的大小比例是8:1。

分配擔保

  若是另外一塊Survivor空間沒有足夠內存來存放上一次新生代收集下來的存活對象,那麼這些對象則直接經過擔保機制進入老年代。

關於分配擔保的內容,我會在講述垃圾收集器時詳細描述。

三:標記-整理算法

  標記-整理算法是根據老年代的特色應運而生。

3.1 標記

  標記過程和標記-清理算法一致(也是基於可達性分析算法)。

3.2 整理

  和標記-清理不一樣的是,該算法不是針對可回收對象進行清理,而是根據存活對象進行整理。讓存活對象都向一端移動,而後直接清理掉邊界之外的內存。

標記-整理算法示意圖

  優勢:不會像複製算法那樣隨着存活對象的升高而下降效率,不像標記-清除算法那樣產生不連續的內存碎片

  缺點:效率問題,除了像標記-清除算法的標記過程外,還多了一步整理過程,效率更低。

四:分代收集算法

  當前商業虛擬機的垃圾收集都是採用「 分代收集 」算法。

根據對象存活週期的不一樣將內存劃分爲幾塊。通常把java堆分爲新生代和老年代。JVM根據各個年代的特色採用不一樣的收集算法。

新生代中,每次進行垃圾回收都會發現大量對象死去,只有少許存活,所以比較適合複製算法。只須要付出少許存活對象的複製成本就能夠完成收集。

老年代中,由於對象存活率較高,沒有額外的空間進行分配擔保,因此適合標記-清理、標記-整理算法來進行回收。

 

 

----對《深刻理解Java虛擬機》第3章垃圾收集器與內存分配策略 3.3小節總結。接下來總結3.5垃圾收集器。

參考:

《深刻理解Java虛擬機》

https://blog.csdn.net/tjiyu/article/details/53983064

相關文章
相關標籤/搜索