深入理解Java虚拟机-判断对象是否存活算法与对象引用

在之前的文章中我们谈到过Java内存区域的概念,我们知道Java中的对象一般存放在堆中,但是总不能让这些对象一直占着内存空间,这些对象最终都会被回收并释放内存,那么我们如何判断对象已经成为垃圾呢?这篇文章会提出两种算法解决这个问题。另外,本文还要谈一谈对象引用相关的知识,这在面试中也是经常被问到的问题。

判断对象是否存活算法

引用计数算法

引用计数算法的原理比较简单,在对象中添加一个引用计数器,当有一个引用指向一个对象时,这个对象的引用计数器会加1,当引用不再指向对象时,引用计数器便减1。当引用计数器的值为0时,说明对象已经成为垃圾。
引用计数算法的优点是算法非常简单,效率也比较高。但是Java并没有使用这种算法管理内存,这是为什么呢?我们先来看看下面这段代码。

public class Demo {
	public static void main(String[] args) {
		Obj obj1 = new Obj();
		Obj obj2 = new Obj();
		obj1.instance = obj2;
		obj2.instance = obj1;
		obj1 = null;
		obj2 = null;
	}
}

class Obj {
	public Obj instance;

	public Obj() {
		super();
	}
}

我们看一下上面这段代码,两个对象obj1obj2instance分别指向对方,造成了循环引用。即便最后obj1obj2都置为空,但它们的instance还是指向对方,如果我们使用这种算法,这两个对象势必无法回收,最终造成内存泄漏。因此,Java没有选择使用引用计数算法管理内存。

可达性分析算法(根搜索算法)

主流的商用编程语言(Java、C#以及上古语言Lisp)都是用这种算法进行对象是否存活的判断。

利用可达性分析算法判定对象是否可回收

根搜索算法利用GC Roots作为起始节点集,从这些节点开始向下搜索,凡是能够到达的节点都是存活节点,不能到达的节点都不再会被使用,这些节点的对象都可以被回收。
Java技术体系中可以作为GC Roots的对象有以下几种:

  • 虚拟机栈(栈帧的本地变量表)中引用的对象

  • 方法区中类静态属性引用的对象

  • 方法区中常量引用的对象

  • 本地方法栈中JNI(及native方法)引用的对象

  • 虚拟机内部的引用,比如基本数据类型对应的Class对象,一些常驻的异常对象(如NullPointerException、OutOfMemoryError)等,还有类加载器。

  • 被同步锁(synchronized)持有的对象

  • 反映Java虚拟机内部情况的JMXBean、JVMTI注册的回调,本地代码缓存等

另外,需要补充的是,即便被可达性分析算法标记为不可达对象,这些对象也未必一定会被回收。事实上,被标记为不可达对象后,这个对象还需要经历第二次标记才可能会被宣布正式死亡。当第一次标记以后,会判断对象有没有必要执行finalize()方法。当对象没有覆盖finalize()方法或已经被虚拟机调用过的话,就被判定没有必要再继续执行了。当有必要执行finalize()方法时,这些对象会被放在名为F-Queue的队列中,随后虚拟机会创建一个线程去执行队列中的对象的finalize()方法。如果这些对象在收集器对F-Queue中对象标记前在finalize()方法中重新与引用链上的对象建立关系,比如将自己赋值给某个类变量就可以移出回收集合,免除被回收的命运。

对象引用

谈到引用,不得不提到前几天的考研复试,我的一位学弟在复试过程中被问到Java中有哪些引用,这几种引用有什么区别。被问到这道题时,他一时语塞,没有回答上来。不过好在没有因为这道题受到影响。今天我们就来谈一谈Java中的四种引用。

  • 强引用。强引用是我们平时使用最多的引用方法。Object obj = new Object()这就是一个典型的强引用实例,只要强引用关系还存在,即使系统内存不足,也不会回收这些对象。

  • 软引用。软引用用来描述一些还有用,但不是必须的对象,使用SoftReference类来实现软引用。当系统内存不足时,会回收软引用关联的对象。

  • 弱引用。弱引用通过WeakReference类来实现,即使内存充足,下一次垃圾收集时,弱引用对象也会被回收。

  • 虚引用。虚引用又称“幽灵引用”或“幻影引用”,是最弱的一种对象引用,它使用PhantomReference类来实现。虚引用的作用是在关联的对象被回收时能收到一个系统通知。

参考文献

深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)
学堂在线-JAVA程序设计进阶

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值