標籤:虛擬機器 jvm 對象 記憶體 記憶體管理
對象已死!
垃圾收集器在對堆進行回收前,首先要做的事情就是要確定這些對象之中哪些還“存活”著, 哪些已經“死去" (即不可能再被任何途徑使用的對象)。
1) 引用計數演算法
給每個對象中添加一個引用計數器,每當有一個地方引用它時, 計數器值就加l ; 當引用失效時,計數器值就減l :任何時刻計數器為0 的對象就是不可能再被使用的。引用計數演算法( Reference Counting )的實現簡單,判定效率也很高,在大部分情況下它都是一個不錯的演算法。Java 虛擬機器裡面沒有選用引用計數演算法來管理記憶體,其中最主要的原因是它很難解決對象之間相互循環參考的問題。
2) 可達性分析演算法
就是通過一系列的稱為“GC Roots”的對象作為起始點,從這些節點開始向下搜尋,搜尋所走過的路徑稱為引用鏈(Reference Chain) ,當一個對象到GC Roots 沒有任何引用鏈相連(用圖克的話來說,就是從GC Roots 到這個對象不可達〕時,則證明此對象是不可用。
可作為GC Roots 的對象包括下面幾類:
3) 再談引用
在JDK 1.2之後, Java對引用的概念進行了擴充將引用分為強引用( Strong Reference )、軟引用( Soft Reference)、弱引用( Weak Reference )引、虛引用( Phantom Reference),它們的引用強度依次逐漸減弱。
強引用就是指在程式碼之中普遍在在的。類似Object obj = new Object(),只要強引用還存在,垃圾收集器永遠不會回收據被引用的對象。
軟引用是用來描述一些還有用但並非必需的對象。對於軟引用所聯著的對象。在系統將要發生記憶體溢出異常之前。將會把這些對象列進記憶體回收範圍之中進行第二次回收。如果這次回收還是沒有足夠的記憶體,才會拋出記憶體謐出異常。在JDK1.2 之後,提供了Soft Reference 類來實現軟引用。
弱引用也是用來描述非必需對象的。被弱引用關聯的對象只能生存到下一次垃墩收集發生之前。當垃圾收集器工作肘,無論當前記憶體是否足夠,都會回收掉只被弱引用關聯的對象。在JDK 1.2 之後,提供了WeakReference 類來實現弱引用。
虛引用也稱為幽靈引用或者幻影引用,它是最弱的一種參考關聯性。一個對象是否有虛引用的存在,完全不會對其存留時間構成影響,也無也通過虛引用來取得一個對象執行個體。為一個對象設定虛引用關聯的唯一目的就是希望能在這個對象被收集器回收時收到一個系統通知。在JDK 1.2 之後,提供了PhantomReference 類來實現虛引用。
4) 生存還是死亡
即使在可達性分析演算法中不可邊的對象,也並非是“非死不可”的,,要真正宣告一個對象死亡,至少要經脅兩次標記過程:如果對象在進行可達性分析後發現沒有與GC Roots 相串連的引用鏈,那它將會被第一次標記並且進行一次篩選,篩選的條件是此對象是否有必要執行finalize() 方法。當對象沒有覆蓋fnalize()方法,或者finalize()方法已經被虛擬機器調用過,虛擬機器將這兩種情況都視為“沒有必、要執行”。
如果這個對象被判定為有必要執行finalize()方法,那麼這個對象將會被放置在一個名為F-Queue 的隊列之中,井在稍後由一條由虛擬機器自動建立的、低優先順序的Finalizer線程去執行。 “執行”是指虛擬機器會觸發這個方法,但並不承諾會等待它運行結束。finalize()方越是對象逃脫死亡命運的最後一次機會,稍後GC 將對F-Queue 中的對象進行第二次小規模的標記,如果對象這時候還沒有逃脫,就可以回收了。
5) 方法回收區
方法區( HotSpot 虛擬機器永久代 )垃圾收集主要回收兩部分內容:廢棄常量和無用的類。類需要同時滿足下面3 個條件才能算是“無用的類”:
虛擬機器可以對滿足上述3 個條件的無用類進行回收,但並不一定進行回收。
【參見】【深入理解Java虛擬機器(第二版)】【周志明】
【首發】【http://my.oschina.net/u/245653/blog/388219】
【003】【Java虛擬機器——對象已死判定】