java垃圾回收之如何判斷對象已死

垃圾回收主要管理的就是java堆,因爲虛擬機棧,本地方法棧,都是線程私有的線程消亡,內存自動回收,並且對象在創建過程時,在棧中需要分配多少內存,是明確知道大小的。如何判斷java堆中對象已經失去引用,就顯得尤爲重要。

1.引用計數算法

爲對象添加一個計數器,有引用加1,失去引用,就減1.收集的時候收集,計數器爲0的對象。

這種算法,不被java虛擬機作爲主流的算法所使用,是因爲,java中,對象循環引用,將會造成,計數器永遠不爲0。從而降低收集效率。具體如下:

class Test{
 public Object init;
}

public static void main(arg 0[]){
    Test t1=new Test();
    Test t2=new Test();
    t1.init=t2;
    t2.inti=t1;
    t1=null;
    t2=null;
    System.gc();
}

2.可達性分析算法

通過一系列稱爲“GC Roots”對象作爲起點,從這些節點,向下搜索,搜索所走過的路徑稱爲引用鏈,當一個對象到GCRoots沒有任何引用鏈的時候,證明此對象不可達,也就證明對象沒有引用,則會被回收。

java可以作爲GCroots對象的有:虛擬機棧中本地變量表引用的對象;本地方法棧中native方法引用的對象;方法區中靜態屬性引用的對象;方法區中常量引用的對象;

在內存空間足夠,一些雞肋對象,可以回收,也可以不回收,但是這類對象已經沒有引用。但是還想保留這類對象,所有虛擬機將引用分爲四類。這類雞肋對象,也是一些系統中,放入緩存中的對象。

引用可分爲:強引用,軟引用,弱引用,虛引用四類。

強引用:就是用直接引用的對象,這類對象永遠不會被回收。Object o = new Object();

軟引用:這就是那類還有用,但非必須的對象。在報內存溢出異常之前,gc會第二次回收這類對象,會收完如果內存還不夠,纔會報內存異常。

弱引用:比軟引用還要弱,只能活到下次垃圾收集,無論內存是否夠,都會被垃圾收集器收集。

虛引用:無法通過需引用來獲得對象事例,需引用也不會影響對象的生存週期,設置需引用,就是爲了對象在垃圾回收時,收到一個系統通知。

對象的死亡

可達性算法不可達的對象,在經歷可達性算法分析後,不能達到GCRoots根節點,將被進行一次標記,要真正的回收對象,至少要被標記兩次。如果被第一次標記完成後,會對該對象進行一側篩選,篩選的條件就是,看對象是否有必要執行,finalize()方法。當對象沒覆蓋finalize()方法,或者finalize()方法已經被jvm掉用過,這兩種情況都視爲“沒有必要執行”。如果有必要執行finalize()方法,那麼該對象將被放到F—Queue隊列。jvm將會創建一個低優先級的現場,去執行,觸發對象裏面的finalize()方法。不會等待對象執行完畢,防止由於某個對象的finalize()方法,發生死鎖或者死循環,而導致整個內存回收系統崩潰。

回收方法區

主要回收常量池和無用的類。

回收常量池,常量池中的對象,沒有引用,在內存回收時,則被回收。

無用的類:(1)該類的所有實例均被回收。(2)加載該類的ClassLoader已經被回收。(3)該類對應的java.lang.Class對象沒有任何地方被引用,無法在任何地方通過反射訪問該類的方法。類的回收,和對象回收不同,無用的類,僅僅是可以回收,而不是理馬上被回收。虛擬機提供了,對應的參數,來設置開啓類回收。在大量使用反射,動態代理,CGLib等ByteCode框架、懂贏生成jsp以及OAGI這類頻繁自定義ClassLoader的場景下,需要虛擬機具備類卸載功能,保證不發生內存溢出。

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