无论是通过引用计数算法还是通过可达性分析算法判断对象是否存活都离不开“引用”这个概念,那到底什么是“引用”呢?

Java语言中狭隘的“引用”定义是:如果Reference类型的数据中存储的数值代表的是另一块内存区域的起始地址,就称该Reference数据是代表某块内存(某个对象)的引用。在这种定义下,一个对象只存在两种状态:“被引用”/“未被引用”。这样的定义很严谨,但却缺少了一点灵活的空间,就像这个社会一样,不是所有人都值得活着,那些人民子弟兵值得永远存在,但那些犯罪的恶徒多活一秒都是对社会的污染。在Java中也是一样,堆上的对象不是所有的都是必须的,当内存空间出现紧张时,一些对象将会被抛弃。

JDK 1.2版本后,Java中的引用分为四种类型:强引用(Strongly Reference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(Phantom Reference),这四种引用强度依次减弱。

  1. 强引用(Strongly Reference

强引用是狭隘的引用定义,被引用的对象只会出现两种状态:“被引用”和“未被引用”。这种引用关系很常见,即类似于Object obj = new Object()这种直接赋值的,只要强引用关系还在,堆内的对象就永远不会被回收。

  1. 软引用(Soft Reference

软引用描述的是还有用,但不是必须的一类对象。只被软引用关联着的对象在虚拟机将要发生内存溢出前,会将这类对象列进回收范围之中进行二次回收,如果将它们回收完成后内存还是不足,才会抛出内存溢出异常。Java中提供SoftReference类实现软引用。

  1. 弱引用(Weak Reference

弱引用描述的也是那些非必须对象,但它的强度比软引用要弱一点,被弱引用关联着的对象只能活到下一次垃圾回收发生的时刻。当垃圾回收开始工作时,无论内存是否充足,都会回收掉弱引用的对象。Java中提供了WeakReference类实现弱引用。

  1. 虚引用(Phantom Reference

虚引用是最弱的一种引用关系,一个对象是否有虚引用的存在,完全不会影响该对象的生存周期,也无法通过虚引用得到一个实例对象。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被垃圾回收时收到一个系统通知。Java中提供了PhantomReference类实现虚引用。

参考

  • 《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》 - 周志明