1. 程式人生 > >JVM:GC-判斷物件是否可以回收?

JVM:GC-判斷物件是否可以回收?

今天開始GC,也就是垃圾回收。
GC主要做三個事情:
1、什麼物件可以回收
2、什麼時候進行回收
3、如何回收
jvm裡的垃圾就是物件,指無用的物件,在真正執行垃圾回收前,必須要判斷物件是否是無用,是否可以回收,那麼jvm是如何來判斷一個物件能否回收呢?
今天就來探討一下。

引用計數演算法

方式:給物件維護一個引用計數器,當有一個地方引用到它,則計數器加1,當有引用失效,則計數器減1,當為0時,說明沒有地方引用到這個物件。
優點:實現簡單、效率高
缺點:無法解決迴圈引用。
例:

class Instance{
public Object obj;
public static void main(String[] args){
Instance a = new Instance();
Instance b = new Instance();
a.obj=b;
b.obj=a;
a=null;
b=null;
//a/b由於持有對方的引用,無法被回收,事實上他們已經用不到可以被回收
}
}

可達性分析演算法

方式:從一系列被稱為GC ROOT的物件開始,向下搜尋,搜尋走過的路徑稱為引用鏈,當一個物件到GC ROOT之間沒有引用鏈,說明這個物件不可用。

可作為GC ROOT的物件:
虛擬機器棧中引用的物件,
方法區內類的靜態屬性引用的物件,
方法區常量引用的物件,
本地方法棧中引用的物件

finalize

當一個物件被判定為不可達物件後,也並不是非死不可。
在通過可達性分析演算法判斷沒有引用鏈使之與GC ROOT相連,會判斷該物件是否有必要執行finalize方法:
假如重寫了finalize,並且未呼叫過,則說明有必要執行。

判斷有必要執行finalize的物件,會被放入一個佇列,有jvm建立的低優先順序的Finalizer執行緒去執行。

當在finalize中自救成功的物件,就會在第二次標記時移除即將回收的集合。
自救失敗的就會被回收,不會在執行finalize。

所謂自救就是把自己與引用鏈上的一個物件關聯起來。

JDK1.2,引用概念擴充

強引用:在可達性分析中判斷為物件不可達,則自救失敗的物件會被回收
軟引用:在記憶體不足時會被回收
弱引用:發生GC就會被回收
虛引用:與普通引用沒區別,不影響GC的回收,只是在回收的時候,虛引用引用到的物件會進行一個引用物件,開發人員可以在回收前做一些操作。

方法區內能否GC

方法區內也可以進行GC,只是相對於堆記憶體來說回收的價效比不高。
方法區內的回收主要就是 廢棄常量和無用的類。
廢棄常量的回收條件桶堆內物件,只要沒有地方引用到它即可參與回收。
判斷無用的類需要下面三個條件:
1、該類物件的例項都被回收
2、該類的類載入器被回收
3、該類的Class物件不存在引用,無法在任何地方通過反射訪問