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采用的标记算法。内存

相关文章
相关标签/搜索