Java的四种引用变量

  在Java中是由JVM负责内存的分配和回收,这是它的优点,同时也是它的缺点(不够灵活,垃圾回收对于编程者来说是不可控)。
  在JDK1.2之前,如果一个对象不被任何变量引用,则程序无法再次使用这个对象,这个对象最终会被GC(垃圾回收)。但是如果之后可能还会用到这个对象,就只能去新建一个了,这其实就降低了JVM性能,没有达到最大的优化策略。
  从JDK1.2开始,提供了四种类型的引用:强引用、软引用、弱引用、虚引用。主要的目的如下:

  1. 可以在代码中决定某些对象的生命周期;
  2. 优化JVM的垃圾回收机制;

强引用

  强引用是最普遍的引用,如果一个对象具有强引用,垃圾回收器不会回收该对象,当内存空间不足时,JVM宁愿抛出OutOfMemoryError异常;只有当这个对象没有被引用时,才有可能会被回收。

软引用

  软引用用java.lang.ref.SoftReference类来表示。
  如果一个对象只具有软引用,则有如下特性:

  • 当内存空间足够,垃圾回收器就不会回收它;
  • 当内存空间不足了,就会回收该对象。JVM会优先回收长时间闲置不用的软引用的对象,对那些刚刚构建的或者刚刚使用过的软引用对象会尽可能保留;
  • 如果回收完还没有足够的内存,才会抛出内存溢出异常。只要垃圾回收器没有回收它,该对象就可以被程序使用;
      软引用是用来描述一些有用但并不是必需的对象,适合用来实现缓存,内存空间充足的时候将数据缓存在内存中,如果空间不足了就将其回收掉。

  SoftReference对象是用来保存软引用,但它同时也是一个Java对象。当软引用对象被回收之后,SoftReference对象的get()方法返回null,但SoftReference对象本身并不是null,而此时SoftReference对象已经不再具有存在的价值,需要一个适当的清除机制,避免大量SoftReference对象带来的内存泄漏。
  在SoftReference所对应的软引用的对象被垃圾回收时,JVM会先将SoftReference对象添加到ReferenceQueue这个队列中。当我们调用ReferenceQueue的poll()方法,如果这个队列中不是空队列,那么将返回并移除前面添加的那个Reference对象。

弱引用

  弱引用用WeakReference类来表示;
  弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期,它只能生存到下一次垃圾收集发生之前。当垃圾回收器扫描到只具有弱引用的对象时,无论当前内存空间是否足够,都会回收它。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
  弱引用也可以和一个引用队列联合使用。
  使用场景:一个对象只是偶尔使用,希望在使用时能随时获取,但也不想影响对该对象的垃圾收集,则可以考虑使用弱引用来指向该对象。

虚引用

  虚引用用PhantomReference类来表示。
  与其他三种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。
  虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用 的一个区别在于:虚引用必须和引用队列联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。

在实际程序设计中一般很少使用弱引用和虚引用,使用软引用的情况较多。这是因为软引用可以加速JVM对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出等问题的产生。