Java 垃圾收集器 ---(摘抄,算是筆記)

GC原理

    Java的內存管理實際上就是對象的管理,其中包括對象的分配和釋放。
    對於程序員來說,分配對象使用new關鍵字;釋放對象時,只要將對象所有引用賦值爲null,讓程序不能夠再訪問到這個對象,我們稱該對象爲"不可達的".GC將負責回收所有"不可達"對象的內存空間。
    對於GC來說,當程序員創建對象時,GC就開始監控這個對象的地址、大小以及使用情況。通常,GC採用可達性分析算法確定哪些對象是"可達的",哪些對象是"不可達的".當GC確定一些對象爲"不可達"時,GC就有責任回收這些內存空間。但是,爲了保證GC能夠在不同平臺實現的問題,Java規範對GC的很多行爲都沒有進行嚴格的規定。例如,對於採用什麼類型的回收算法、什麼時候進行回收等重要問題都沒有明確的規定。因此,不同的JVM的實現者往往有不同的實現算法。

    

1、引用計數法

給對象添加一個引用計數器,每當有地方引用它,計數器 +1;每當一個引用此對象的引用失效,計數器 -1 ;任何計數器值等於 0 時,這個對象就不能在被使用。這種方法實現簡單,判定效率也很高,但是難以解決對象之間相互循環引用的問題


2、可達性分析法

主流的程序語言(Java 、C#,Lisp)使用時可達性分析法來判定對象是否存活的。算法的基本思路是:通過一系列的“GC Roots”對象作爲起點,從這些起點開始向下搜索,搜索到所走過的路徑成爲“引用鏈(Reference Chain)”當前一個對象到GC Roots沒有任何引用鏈相連(就是圖論中說的對象不可達時),說明此對象不可用。




Java 中作爲GC Roots 的對象包括下面四種:

1、虛擬機棧(棧中的本地變量表)中引用的對象

2、方法區中類靜態屬性引用的對象

3、方法區中常量引用的對象

4、本地方法棧中JNI(即一般說的Native 方法)引用的對象


在可達性分析算法中不可達的對象,也並不是非死不可,只是暫時處於“緩刑”階段。宣告 對象死亡 至少要經歷兩次標記過程:對象進行第一可達性分析之後發現沒有與GC Roots 相連的引用鏈,它會被第一次標記並且進行一次篩選,篩選的條件是:此對象是否有必要執行 finalize( )方法。當對象沒有覆蓋finalize( )方法,或者finalize( )方法已經被虛擬機調用過,虛擬機將這兩種情況都視爲“沒有必要執行” 。

如果這個對象被判定有必要執行finalize( )方法,那麼這個對象將會放置在一個F-Queue 隊列中,稍後由虛擬機自動建立的、低優先級的Finalizer線程去執行(觸發這個方法)它。finalize()方法是對象逃脫死亡的最後一次機會,稍後GC 將對F-Queue對象進行第二次小規模的標記,如果對象要在finalize()中成功解救自己只要重新與引用鏈上的任何一個對象建立關聯即可,那麼它將在第二次標記時被移除“即將回收”的集合;如果還沒有逃脫那基本上就真的被回收了。

5.方法區回收

方法區(永久代)垃圾回收的主要回收 兩 部分內容:廢棄的常量無用的類

廢棄的常量:沒有任何對象引用常量池中的該常量(字面量);也不存在其他地方對該常量(字面量)的引用。

無用的類:1、該類所有的是實例對象都已被回收,或者說堆中沒有該類的任何實例。2、加載該類的ClassLoader 已經被回收。3、該類對應的Java.lang.Class對象沒有在任何地方被引用。無法在任何地方通過反射訪問的方式方位該類的方法。

6.垃圾收集算法

  一、標記清除算法:

        標記出所有要回收的對象,標記完成後統一回收所有被標記的對象。缺點:1.效率問題,標記和清除的效率都不高。2.容易產生大量不連續的內存碎片,導致給較大兌現分配內存空間時無法找到滿足內存需求的連續空間而不得不進行另一次的垃圾回收操作

  二、複製算法:

        將內存劃分爲相等的兩塊,每次只用其中的一塊,這塊內存用完了,將還活着的對象複製到另一塊內存上。這塊內存一次性清理掉。

  三、標記整理算法

        讓或者對象都向內存的一端移動,然後清理掉邊界以外 的內存。

所謂的分代收集算法就是在不同的 代 次用上述三中不同的收集算法。新生代採用複製算法,老年代採用一或者三算法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章