JVM 垃圾回收GC
一、如何判斷物件是垃圾物件
1.引用計數法
在物件中新增一個引用計數器,當有地方引用這個物件的時候,引用計數器的值+1,失效則-1。但是兩個相互引用的物件有可能無法回收。
private Object instance; Demo demo1 = new Demo(); Demo demo2 = new Demo(); demo1.instance = demo2; demo2.instance = demo1; demo2 = null; demo1 = null; System.gc();
2.可達性分析
根據GCRoots節點來搜尋,遍歷過得路徑,當物件不再引用鏈上,則物件可以被回收(沒有被引用)。
GCRoots物件:
虛擬機器棧、方法去中類屬性引用的物件、方法區中常量引用的物件、本地方法棧中引用的物件。
二、如何回收
1.回收策略
(1)標記-清除
1.標記:標記出需要回收的物件
2.清除:清除無效的物件
缺點:清除物件過程中,將物件記憶體佔用的記憶體清空,但不會整理記憶體空間,這導致記憶體的地址是不連續的。當需要分配新物件的記憶體時,需要在記憶體的一張維護表裡面尋找可用的連續的記憶體,如果沒有找到則會觸發GC。 這樣會造成效率的浪費和空間記憶體的浪費。
(2)複製
堆記憶體分為 一個eden和兩個survivor區域,記憶體比例是8:1:1。在未發生GC前,記憶體中產生的物件儲存在eden區域和一個Survivor區域。當著兩個區域都存滿時,會觸發GC,將存活下來的物件例項儲存到第二個survivor區域。這個區域和eden區域將會作為新的記憶體區域來存放新產生的物件。
(3)標記-整理 (針對老年代回收的演算法)
標記需要清除的物件,將需要清除的物件和保留的物件移動至兩個區域,進而清除物件。這樣的演算法可以使得清楚後的記憶體區域是完整連續的區域。
(4)分代收集演算法
分代收集演算法是根據不用的區域採用不用的演算法來進行GC,新生代區域採用複製演算法,老年代採用標記-整理演算法。這樣的分配規則使得不同區域的GC效能更加高效。