標籤:style 搜尋 this 棧幀 start 地方 垃圾收集器 img 作用
在堆中存放著幾乎所有的對象執行個體,垃圾收集器在對堆進行回收前,第一件事就是要確定這些對象之中哪些還活著,哪些對象已經死去.判斷對象是否已經死亡有以下幾種演算法:
- 引用計數法演算法
定義 : 給對象中添加一個引用計數器,當有一個地方引用時,計數器加1,引用失效時,就減1,當對象的引用計數器為0時,對象就是不可再被使用的.特點 : JAVA虛擬機器中很少使用這種演算法,主要原因是它很難解決對象之間的循環參考問題
- 可達性分析演算法
定義 : 通過一系列的稱為 GC Roots 的對象作為起點,從這些節點開始向下搜尋,搜尋把走過的路徑稱為引用鏈,當一個對象到 GC Roots 沒有任何引用鏈相連(就是從GC Roots 到這個對象不可達)時,則證明此對象是停用.如 中的 5,6,7 對象就是不可達的,就是停用. 1) 哪些對象可以作為 GC Roots 對象呢?1 虛擬機器棧(棧幀中的本地變數表)中引用的對象2 方法區中類靜態屬性引用的對象3 方法區中常量引用的對象4 本地方法棧中JNI引用的對象 2) 再談引用:(從上到下依次減弱)1 強引用 : 只要強引用還存在,垃圾收集器永遠不回收被引用的對象2 軟引用 : 在記憶體溢出異常之前,回收對象3 弱引用 : 在下一次 GC 時,無論當前記憶體是否足夠,都會回收被引用的對象4 虛引用 : 沒用,唯一的用處是在對象回收時,會收到一個系統通知 3) 對象的 finalize() 方法作用生存還是死亡?即使在可達性分析演算法中不可達的對象,也並非是"非死不可"的,這時候它們暫時處於"緩刑"階段,要真正宣告一個對象死亡,至少要經曆2次標記:1 如果對象在進行可達性分析後發現對象不可達,那它將會被第一次標記並進行一次篩選,篩選的條件是此對象是否有必要執行finalize()方法.當對象沒有覆蓋finalize()方法,或者finalize()方法已經執行過,虛擬機器將這種情況視為沒有必要執行 2 如果對象被判定為有必要執行finalize()方法,那麼這個對象將會放置在一個叫做F-Queue的隊列之中,並在稍後由一個由虛擬機器自動建立的,低優先順序的Finalizer線程去執行它.這裡所謂的招行是指虛擬機器會觸發這個方法,但並不承諾等待它運行結束,這樣做的原因是,如果一個對象在finalize()方法中做耗時的操作,將很可能會導致 F-Queue隊列中的其它對象永久處於等待,甚至導致整個記憶體回收系統線程崩潰, finalize()方法是對象逃脫死亡命運的最後一次機會,稍後GC將對F-Queue中的對象進行第二次標記,如果對象要在finalize()中成功拯救自己,即只要對象重新和引用鏈上的任何一個對象發生關聯即可,即將自己(this關鍵字)賦值給某個類變數或者對象的成員變數,那麼在第二次標記時它將被移出"即將回收"的集合,如果對象這時候還沒有逃脫,那麼基本上它真的要被回收了注:盡量不要用finalize()方法,忘了這個方法
4 Java 如何判定是否存活或者死亡