Java中的强引用、弱引用、软引用和虚引用

前言

在看 JDK 中 ThreadLocal 源码时接触到了弱引用 WeakReference,在这次的笔记中记录下强引用、弱引用、软引用和虚引用的概念与区别。

四种引用的级别由高到低依次为:

Strong Reference > Soft Reference > Weak Reference > Phantom Reference

Reference

强引用(Strong Reference)

强引用是最常使用的引用,任何被强引用所引用的对象都不能被垃圾回收器回收。当内存空间不足,JVM 就会抛出 OutOfMemoryError 错误。

1
Object obj = new Object();

变量 obj 就是该 Object 对象的一个强引用。只有强引用消失,对象才能被 GC 回收。

如果在一个方法的内部有一个强引用,这个引用保存在 Java 栈中,而真正的引用内容(Object)保存在 Java堆中。 当这个方法运行完成后,就会退出方法栈,则引用对象的引用数为0,这个对象会被回收。

弱引用(Weak Reference)

相比于软引用,具有弱引用的对象拥有更短暂的生命周期。当一个对象只有弱引用指向它时,垃圾回收器不管当前内存是否足够,都会进行回收。

在 ThreadLocal 中的 ThreadLocalMap 的 key 就被设计成了弱引用类型,在 JDK 中另一个使用弱引用的例子是WeakHashMap,它是除 HashMap 和 TreeMap 之外Map接口的另一种实现。WeakHashMap中的 key 也是弱引用类型。

软引用(Soft Reference)

软引用用来描述一些有用但是非必需的对象。如果一个对象只具有软引用,当内存空间足够时垃圾回收器就不会回收它。如果内存空间不足了,才会回收这些对象的内存。

软引用用来描述一些有用但并不是必需的对象,比如可用来实现内存敏感的高速缓存。

虚引用(Phantom Reference)

虚引用不同于其余三种引用,也无法通过虚引用获得对象的一个实例,虚引用并不会决定对象的生命周期。

如果一个对象仅持有虚引用,那么它就和没有任何引用一样,为一个对象设置虚引用关联的唯一目的就是希望这个对象被 GC 回收时能收到一个系统通知,即用来跟踪对象被垃圾回收器回收的活动。

虚引用与软引用和弱引用的区别在于:

虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。

总结

引用类型 何时会被垃圾回收 用途 生命周期
强引用 从不 / JVM停止运行时终止
弱引用 当内存不足时 缓存 内存不足时终止
软引用 正常GC时 缓存 GC后终止
虚引用 正常GC时 跟踪对象的垃圾回收 GC后终止

一个对象的生命周期:

Reference

  • 本文作者: Marticles
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!