JVM中如何判断对象死亡?

在堆内存中存放的Java对象实例,就要首先判断这些对象哪些对象还"存活"着,哪些已经:“死去”,这时,出现了判断对象是否存活的2种算法: 引用计数法和可达性分析法.,下面一一道来:

1. 引用计数法

思想: 给每个对象中添加一个引用计数器, 每当有一个计数器引用它,计数器值就加1; 当引用失效, 计数器的值就减1; 任何时刻计数器为0的对象就是不可能再被使用的.即垃圾回收器可以回收的.
优点:引用计数法实现简单, 但效率不高,大多数情况下都是个不错的算法,例如微软的COM(component Object Model)技术, 使用ActionScript3的FlashPlayer,Python语言和游戏脚本领域被广泛应用的Squirrel中都用了引用计数算法进行内存管理.
缺点:很难解决对象之间的相互循环引用的问题
例如如下代码:

public class Test {
	public Object instance = null;
	private static final int _1MB = 1024*1024;
	/**
	 * 此成员作用,占用内存,以便能在gc日志中看清是否被回收过
	 */
	private byte[] bigSize = new byte[2*_1MB];
	public static void testGC() {
		Test obj1 = new Test();
		Test obj2 = new Test();
		obj1.instance = obj2;
		obj2.instance = obj1;
		obj1 = null;
		obj2 = null;
		
		System.gc();
	}
}

实际上这2个对象已经不可能被访问到, 但他们互相引用对方,导致引用计数器值都不为0;于是这种算法就不能回收了

2. 可达性分析算法

在Java,C#,等语言中,都是通过可达性分析算法来判断对象是否存活.
思想:通过一系列称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索, 搜索走过的路径称为引用链,当一个对象到GC Roots没有任何引用链时,则证明此对象已经死亡(不可用).如下:
在这里插入图片描述
黄色为仍然存活的对象; 白色为判定可回收的对象
Java语言中, 可作为GC Roots的对象包括下面几种:

  • (1) 虚拟机栈中(栈帧中的本地变量表)引用的对象;
  • (2)方法区中类静态属性引用的对象
  • (3)方法区中常量引用0的对象
  • (4)本地方法栈中JNI(即native方法)引用的对象
    引用的分类:强引用,软引用,弱引用,虚引用

猜你喜欢

转载自blog.csdn.net/lq1759336950/article/details/99611066