JVM判斷對象是否存活

  • 引用計數法
  • 可達性分析算法

引用計數法

給對象添加一個引用計數器,每當有一個地方引用,計數器就加1,當引用失效,計數器減1,計數器爲0的對象沒有被使用,Java中沒有使用引用計數法,緣由是引用計數法沒法解決對象間的循環引用問題。

package com.rumenz;
public class Testy {
    public Object instance = null;
    public static void main(String[] args) throws InterruptedException {
        Testy objA = new Testy();
        Testy objB = new Testy();
        objA.instance = objB;
        objB.instance = objA;
        objA = null;
        objB = null;
        //假設在這行發生了gc,objA和objB是否被回收
        System.gc();
        //拖延時間查看堆內存對象
        Thread.sleep(50000);
    }
}

VM設置參數算法

-XX:+PrintGCDetails -XX:-UseAdaptiveSizePolicy -XX:SurvivorRatio=8 -XX:NewSize=10M -XX:MaxNewSize=10M

-XX:+PrintGCDetails 啓用日誌
-XX:-UseAdaptiveSizePolicy 禁用動態調整,使SurvivorRatio能夠起做用
-XX:SurvivorRatio=8 設置Eden:Survivior=8
-XX:NewSize=10M -XX:MaxNewSize=10M 設置整個新生代的大小爲10Mspa

使用jmap -histo pid查看堆內的對象3d

斷開棧和堆對象的引用

objA = null;
objB = null;

jmap -histo pid日誌

堆中未發現 com.rumenz.Testy對象。雖然 objAobjB存在相互引用,可是因爲棧和堆對象沒有了引用關係, 垃圾回收時將 objAobjB回收掉,說明JVM虛擬機未使用引用計數法來判斷對象是否存活。

未斷開棧和堆對象的引用

//objA = null;
//objB = null;

jmap -histo pidcode

堆中發現com.rumenz.Testy對象。由於對象還在使用着。對象

可達性分析算法

GC Root對象爲起點,從這些對象爲起點,往下搜索,走過的路徑爲引用連,當一個對象到GC Roots沒有任何引用連引用,則證實此對象沒有被用到,將會被JVM斷定爲垃圾。blog

img

JDK1.8中什麼是GC Root

  • 虛擬機棧中(棧幀中的本地變量表)中引用的對象。
  • 元數據區類靜態屬性引用的對象
  • 元數據區常量引用的對象
  • 本地方法棧(Native)方法引用的對象

相對於引用計數法,可達性分析避免了循環致使的問題。同時具有執行搞笑的特色。也是JVM採用的標記算法。內存

相關文章
相關標籤/搜索