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物件不存在引用,無法在任何地方通過反射訪問