java 垃圾回收步步深入02----判斷對象是否已死

                                           java 垃圾回收步步深入02----判斷對象是否已死  

 1.引用計數法

        堆中每一個對象都有一個引用計數。當新創建一個對象,或者有變量被賦值爲這個對象的引用,則這個對象的引用計數加1;當一個對象的引用超過生存期或者被設置一個新的值時,這個對象的引用計數減1。當對象的引用計數變爲0時,就可以被當作垃圾收集。

        在引用的時候+1,在釋放的時候-1,在發現計數值爲0的時候這塊內存就不再需要了。但是爲什麼很多地方都不會使用引用計數?最致命的問題引用計數只是一個充分非必要條件,也就是說:引用計數爲0的時候內存不會再被使用,而不會再被使用的內存引用計數不一定爲0。最簡單的例子就是循環引用了:如果A引用了B,同時B又引用了A,那麼這兩對象的計數永遠也都不會是0了(那麼這兩個對象佔用的空間也當然用於不會釋放)

       這種方法的好處是垃圾收集較快,適用於實時環境。缺點是這種方法無法監測出循環引用。例如對象A引用對象B,對象B也引用對象A,則這兩個對象可能無法被垃圾收集器收集。因此這種方法是垃圾收集的早期策略,現在很少使用。

          

2.跟蹤法

     這種方法把每個對象看作圖中一個節點,對象之間的引用關係爲圖中各節點的鄰接關係。垃圾收集器從一個或數個根結點遍歷對象圖,如果有些對象節點永遠無法到達,則這個對象可以被當作垃圾回收。

     容易發現,這種方法可以檢測出循環引用,避免了引用計數法的缺點,較爲常用。

   跟蹤法又稱爲“標記並清除”策略。基本思想是從根對象開始遍歷整個對象圖,仍然被引用的對象打上標記,遍歷結束後,沒有被打上標記的對象就可以清除。記錄標記的策略可以在對象本身記錄或者通過位圖來記錄。

跟蹤收集器通常使用兩種策略來實現:

1.壓縮收集器:遍歷的過程中如果發現對象有效,則立刻把對象越過空閒區滑動到堆的一端,這樣堆的另一端就出現了一個大的連續空閒區,從而消除了堆碎片。

2.拷貝收集器:堆被分爲大小相等的兩個區域,任何時候都只使用其中一個區域。對象在同一個區域中分配,直到這個區域被耗盡。此時,程序執行被中止,堆被遍歷,遍歷時被標記爲活動的對象被拷貝到另外一個區域。這種做法用稱之爲“停止並拷貝”。

這種做法的主要缺點是:太粗暴,要拷貝就都拷貝,粒度太大,整體性能不高。因此就有了更先進的“按代收集的收集器”


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