深刻理解java虛擬機之——JVM垃圾回收策略總結

  • 如何判斷一個對象是否存活

  引用計數算法:給對象中添加一個引用計數器,每當有引用它時,計數器值就加1;當引用失效時,計數器值就減1;任什麼時候刻計數器爲0的對象就是不可能再被使用。算法

   Java虛擬機裏面沒有選用引用計數算法來管理內存,其中主要緣由是他很難解決對象間相互引用的問題。spa

    例如:對象objA和objB都有字段instance字段,且互相賦值,但實際上這兩個對象已經不可線程

  能被訪問了,但由於他們互相引用着對方,致使他們的引用計數都不爲0,因而致使他們沒法回收。code

  (Java中這種狀況是能夠回收的)對象

public class ReferenceGC { public Object instance = null; public static void testGC(){ ReferenceGC objA = new ReferenceGC(); ReferenceGC objB = new ReferenceGC(); objA.instance = objB; objB.instance = objA; objA = null; objB = null; } }

     可達性分析算法經過一系列的稱爲"GC Root"的對象做爲起點,從這些節點開始向下搜索,blog

  搜素所走過的路徑稱爲引用鏈(Reference Chain),當一個對象到GC Root沒有任何的引用鏈隊列

  相連,就斷定對象能夠被回收。Java, C#等語言都是使用這種算法判讀對象的存活的。內存

    GC Root的對象包括下面幾種:字符串

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

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

      方法區中常量引用的對象

      本地方法棧中JNI(Native方法)引用的變量

  • 引用

    Java1.2後對引用進行擴充,分爲:

      強引用:相似 Object obj = new Object()這類引用,垃圾收集器永遠不會進行回收

      軟引用:用來描述一些還有用但非必須的對象。系統在內存溢出異常以前,將會把這些

    對象列入回收範圍之中進行。二次回收。若是此次回收尚未足夠的內存,纔會拋出內存異常。

    SoftReference類實現。

      弱引用:比軟引用更弱一些,也是用來描述非必須對象。回收發生在下次垃圾收集器回收時。

    WeakReference類實現。

      虛引用:最弱一種引用,虛引用沒法影響對象其生存時間,也沒法經過虛引用得到

    對象,惟一目的就是對象被垃圾收集器回收時,收到一個系統通知。PhantomReference類實現。

  • 對象生存仍是死亡

    若是對象在進行可達性分析後發現沒有與GC Roots相連的引用鏈,那麼它將會被第一次標記而且進行

  一次篩選,篩選條件是該對象是否覆蓋finalize()方法,是否執行過finalize()方法。若是爲覆蓋或執行過則

  對象死亡。

    若是覆蓋finalize()且有必要執行finalize(),則對象放入F-Queue的隊列中,以後由虛擬機自動創建,

  低優先級的Finalizer線程去執行這裏的執行是指虛擬機會觸發這個方法,但不承諾會等待它運行結束。

  (該方法不建議使用

  • 方法區回收

    方法區主要回收:廢棄常量無用的類 

    廢棄常量:例如一個字符串"abc"已經進入常量池中,可是當前系統沒有其餘地方引用這個字面量。 

    無用的類:

      該類的全部實例都已經被回收,也就是Java堆中不存在該類的任何實例

      加載該類的ClassLoader已經被回收

      該類對應的Java.lang.Class對象沒有在任何地方被引用,沒法再任何地方經過反射訪問該類的

    方法。

  • 垃圾收集算法

    標記-清除算法:首先標記出全部須要回收的對象,在標記完成後統一回收全部標記的對象,標記過

  程在上面提過。

    不足:1.效率問題,標記和清除兩個過程效率不高

       2.空間問題,標記清楚產生大量內存碎片

    複製算法:將內存安裝容量分爲大小相等的兩塊,每次使用其中一塊。當回收時,將存活的對象複製到

  爲使用的內存中,清楚已使用過的內存。

    不足:內存縮小到運來的一半

    Java在新生代中採用這種算法,不過是將內存分爲Eden和兩塊Survivor,每次使用Eden和其中的Suvivor

  當回收時,將Eden和Suvivor存活的內存複製到未使用的Suvivor空間。HotSpot默認Eden與Suvivor比例爲

  8:1,至關於可使用90%的內存,若是存活的內存超過Suvivor空間,就是用老年代進行分配擔保。

    標記-整理算法:過程與標記-清除算法同樣,但後續步驟不是直接對可回收對象進行清理,而是讓全部存活

  的對象向一端移動,而後清理掉端邊界之外的內存。

    分代收集算法:將內存劃分紅幾塊,各個區域採用最適當的收集算法。Java通常把Java堆分爲新生代和老年代,

  按各個年代特色採用適當的算法。

  垃圾收集器:

    新生代:Serial收集器,ParNew收集器,Parallel Scavenge收集器

    老年代:CMS, Seral Old(MSC), Parallel Old收集器

    GI收集器

相關文章
相關標籤/搜索