JVM GC 算法

根搜索算法

根搜索算法是從離散數學中的圖論引入的,程序把所有引用關係看作一張圖,從一個節點GC ROOT 開始,尋找對應的引用節點,找到這個節點後,繼續尋找這個節點的引用節點。當所有的引用節點尋找完畢後,剩餘的節點則被認爲是沒有被引用到的節點,即無用的節點。
在這裏插入圖片描述
上圖紅色爲無用的節點,可以被回收。
目前Java中可以作爲GC ROOT的對象有:
1、虛擬機棧中引用的對象(本地變量表)
2、方法區中靜態屬性引用的對象
3、方法區中常量引用的對象
4、本地方法棧中引用的對象(Native對象)
基本所有GC算法都引用根搜索算法這種概念。

標記 - 清除算法

在這裏插入圖片描述
標記-清除算法採用從根集合進行掃描,對存活的對象進行標記,標記完畢後,再掃描整個空間中未被標記的對象進行直接回收,如上圖。
標記-清除算法不需要進行對象的移動,並且僅對不存活的對象進行處理,在存活的對象比較多的情況下極爲高效,但由於標記-清除算法直接回收不存活的對象,並沒有對還存活的對象進行整理,因此會導致內存碎片。

複製算法

在這裏插入圖片描述
複製算法將內存劃分爲兩個區間,使用此算法時,所有動態分配的對象都只能分配在其中一個區間(活動區間),而另外一個區間(空間區間)則是空閒的。
複製算法採用從根集合掃描,將存活的對象複製到空閒區間,當掃描完畢活動區間後,會的將活動區間一次性全部回收。此時原本的空閒區間變成了活動區間。下次GC時候又會重複剛纔的操作,以此循環。
複製算法在存活對象比較少的時候,極爲高效,但是帶來的成本是犧牲一半的內存空間用於進行對象的移動。所以複製算法的使用場景,必須是對象的存活率非常低才行,而且最重要的是,我們需要克服50%內存的浪費。

標記 - 整理算法

在這裏插入圖片描述
標記-整理算法採用 標記-清除 算法一樣的方式進行對象的標記、清除,但在回收不存活的對象佔用的空間後,會將所有存活的對象往左端空閒空間移動,並更新對應的指針。標記-整理 算法是在標記-清除 算法之上,又進行了對象的移動排序整理,因此成本更高,但卻解決了內存碎片的問題。

JVM爲了優化內存的回收,使用了分代回收的方式,對於新生代內存的回收(Minor GC)主要採用複製算法。而對於老年代的回收(Major GC),大多采用標記-整理算法。