从 JDK 1.2 版本开始,把对象的引用分为 4 种级别,从而使程序能更加灵活地控制对象的生命周期。

这 4 种级别由高到低依次为:强引用、软引用、弱引用和虚引用。

强引用(Strongly Re-ference)

在 Java 中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用。当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的。当内存空间不足,即使该对象以后永远都不会被用到,Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。因此强引用是造成 Java 内存泄漏的主要原因之一。

软引用(Soft Reference)

软引用需要用 SoftReference 类来实现,对于只有软引用的对象来说,当系统内存足够时它不会被回收,当系统内存空间不足时它会被回收。软引用通常用在对内存敏感的程序中。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java 虚拟机就会把这个软引用加入到与之关联的引用队列中。

弱引用(Weak Reference)

弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。弱引用需要用 WeakReference 类来实现,它比软引用的生存期更短,对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管 JVM 的内存空间是否足够,总会回收该对象占用的内存。

弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java 虚拟机就会把这个弱引用加入到与之关联的引用队列中。

虚引用(Phantom Reference)

“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。

虚引用需要 PhantomReference 类来实现,它不能单独使用,必须和引用队列联合使用。虚引用的主要作用是跟踪对象被垃圾回收的状态

虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。

总结

引用类型主要分为强软弱虚四种:

  • 强引用指的就是代码中普遍存在的赋值方式,比如 A a = new A()这种。强引用关联的对象,永远不会被 GC 回收。
  • 软引用可以用 SoftReference 来描述,指的是那些有用但是不是必须要的对象。系统在发生内存溢出前会对这类引用的对象进行回收。
  • 弱引用可以用 WeakReference 来描述,他的强度比软引用更低一点,弱引用的对象下一次 GC 的时候一定会被回收,而不管内存是否足够。
  • 虚引用也被称作幻影引用,是最弱的引用关系,可以用 PhantomReference 来描述,他必须和 ReferenceQueue 一起使用,同样的当发生 GC 的时候,虚引用也会被回收。可以用虚引用来管理堆外内存。