乐趣区

关于jvm: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 设置整个新生代的大小为 10M

应用 jmap -histo pid 查看堆内的对象

断开栈和堆对象的援用

objA = null;
objB = null;

jmap -histo pid

堆中未发现 com.rumenz.Testy 对象。尽管 objAobjB存在互相援用,然而因为栈和堆对象没有了援用关系, 垃圾回收时将 objAobjB回收掉,阐明 JVM 虚拟机未应用援用计数法来判断对象是否存活。

未断开栈和堆对象的援用

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

jmap -histo pid

堆中发现 com.rumenz.Testy 对象。因为对象还在应用着。

可达性剖析算法

GC Root 对象为终点,从这些对象为终点,往下搜寻,走过的门路为援用连,当一个对象到 GC Roots 没有任何援用连援用,则证实此对象没有被用到,将会被 JVM 断定为垃圾。

JDK1.8 中什么是 GC Root

  • 虚拟机栈中 (栈帧中的本地变量表) 中援用的对象。
  • 元数据区类动态属性援用的对象
  • 元数据区常量援用的对象
  • 本地办法栈 (Native) 办法援用的对象

绝对于援用计数法,可达性剖析防止了循环导致的问题。同时具备执行搞笑的特点。也是 JVM 采纳的标记算法。

退出移动版