JVM判断对象是否存活

  • 引用计数法
  • 可达性分析算法

引用计数法

给对象添加一个引用计数器,每当有一个地方引用,计数器就加1,当引用失效,计数器减1,计数器为0的对象没有被使用,Java中没有使用引用计数法,原因是引用计数法无法解决对象间的循环引用问题。

图片alt

  1. package com.rumenz;
  2. public class Testy {
  3. public Object instance = null;
  4. public static void main(String[] args) throws InterruptedException {
  5. Testy objA = new Testy();
  6. Testy objB = new Testy();
  7. objA.instance = objB;
  8. objB.instance = objA;
  9. objA = null;
  10. objB = null;
  11. //假设在这行发生了gc,objA和objB是否被回收
  12. System.gc();
  13. //拖延时间查看堆内存对象
  14. Thread.sleep(50000);
  15. }
  16. }

VM设置参数

  1. -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查看堆内的对象

断开栈和堆对象的引用

  1. objA = null;
  2. objB = null;

图片alt

jmap -histo pid

堆中未发现com.rumenz.Testy对象。虽然objAobjB存在相互引用,但是由于栈和堆对象没有了引用关系, 垃圾回收时将objAobjB回收掉,说明JVM虚拟机未使用引用计数法来判断对象是否存活。

未断开栈和堆对象的引用

  1. //objA = null;
  2. //objB = null;

jmap -histo pid

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

可达性分析算法

GC Root对象为起点,从这些对象为起点,往下搜索,走过的路径为引用连,当一个对象到GC Roots没有任何引用连引用,则证明此对象没有被用到,将会被JVM判定为垃圾。

图片alt

JDK1.8中什么是GC Root

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

相对于引用计数法,可达性分析避免了循环导致的问题。同时具备执行搞笑的特点。也是JVM采用的标记算法。

返回笔记列表
入门小站