在 Java 中,除了 强引用(Strong Reference) 外,JVM 还定义了其他四种引用类型,用于更精细地控制对象的生命周期与垃圾回收行为。
这五种引用类型在 java.lang.ref 包中定义,是 GC 判断对象可回收性的关键依据。


🌳 一、五种引用类型总览

引用类型 类名 是否可被 GC 回收 典型用途
1. 强引用(Strong Reference) 普通对象引用 ❌ 永不回收(除非引用断开) 普通对象使用
2. 软引用(Soft Reference) SoftReference<T> ⚠️ 内存不足时回收 缓存系统(如图片缓存)
3. 弱引用(Weak Reference) WeakReference<T> ✅ 下一次 GC 就回收 ThreadLocal、WeakHashMap
4. 虚引用(Phantom Reference) PhantomReference<T> ✅ 对象回收前收到通知 跟踪对象销毁、管理堆外内存
5. Final 引用(Final Reference) JVM 内部使用 ✅ 回收前执行 finalize() 已过时机制,替代为 Cleaner

💪 1. 强引用(Strong Reference)

定义: 普通变量引用对象时即为强引用,例如:

Object obj = new Object();

特性:

  • 只要强引用还存在,GC 永远不会回收该对象。

  • 是 Java 中最常见的引用类型。

  • 若想回收,必须显式断开引用:

    obj = null; // 解除引用
    

🧩 2. 软引用(Soft Reference)

定义: 使用 SoftReference 包装对象,例如:

SoftReference<Object> ref = new SoftReference<>(new Object());

特性:

  • 内存不足 时,GC 会回收这些对象。

  • 常用于缓存系统(如图片缓存、网页缓存)。

  • 可通过 ref.get() 获取引用对象(若未被回收)。

  • 示例:

    Object obj = ref.get();
    if (obj == null) {
        // 被回收了,需要重新加载
    }
    

🪶 3. 弱引用(Weak Reference)

定义: 使用 WeakReference 包装对象,例如:

WeakReference<Object> ref = new WeakReference<>(new Object());

特性:

  • 只要进行 一次 GC,即使内存充足,对象也会被回收。

  • 常用于:

    • WeakHashMap
    • ThreadLocal
    • 避免内存泄漏的缓存
  • 调用 ref.get() 若返回 null,说明对象已被回收。


👻 4. 虚引用(Phantom Reference)

定义: 使用 PhantomReference 创建:

ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> ref = new PhantomReference<>(new Object(), queue);

特性:

  • ref.get() 永远返回 null

  • 对象被回收前会被放入 ReferenceQueue,用于做资源清理通知

  • 常用于:

    • 管理 堆外内存(DirectByteBuffer)
    • 跟踪对象销毁(类似于回调机制)
  • 示例:

    if (queue.poll() != null) {
        // 对象即将被回收,可做清理
    }
    

🧱 5. Final 引用(Final Reference)

定义:

  • 这是 JVM 内部使用的一种引用类型。
  • 当对象覆盖了 finalize() 方法且尚未执行时,会被 FinalReference 暂时引用。
  • 在调用 finalize() 之后,GC 会回收该对象。

特性:

  • 性能差、不确定性高,已不推荐使用
  • Java 9+ 建议改用 java.lang.ref.Cleaner

🧠 六、总结对比表

特性 强引用 软引用 弱引用 虚引用 Final 引用
可否被 GC 回收 内存不足时 下一次 GC 任何时刻 finalize 后
get() 可用
用途 常规对象 缓存 映射、缓存 跟踪回收、堆外资源 清理前处理
典型类 Object SoftReference WeakReference PhantomReference Finalizer

🧩 一、ReferenceQueue 是什么?

ReferenceQueue 是 java.lang.ref 包中的一个类,用来配合各种引用类型(Soft、Weak、Phantom)使用。
它的作用是:

当被引用的对象即将被 GC 回收时,JVM 会把对应的引用对象(不是被引用的对象本身!)放入这个队列中。

这样我们就能知道:

哪些对象已经“死亡”(即将或已经被回收);

从而可以在程序中执行额外的清理逻辑(如释放堆外资源、移除缓存项等)。

🧠 二、ReferenceQueue 的工作原理

[被引用对象] ← 被包装在 ——> [引用类型对象(Soft/Weak/Phantom)]
                                           ↓
                               (被 GC 回收后)
                                           ↓
                            [放入 ReferenceQueue 队列]

也就是说:

当对象被 GC 判定为不可达时;

对应的 SoftReference / WeakReference / PhantomReference
就会被加入到关联的 ReferenceQueue;

程序可以从队列中取出这个引用对象,从而“得知”它指向的对象已被回收。
image