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


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

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

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

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

  能被訪問了,但因為他們互相引用着對方,導致他們的引用計數都不為0,於是導致他們無法回收。

  (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"的對象作為起點,從這些節點開始向下搜索,

  搜素所走過的路徑稱為引用鏈(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收集器

 

  




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM