在 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,即使内存充足,对象也会被回收。
-
常用于:
WeakHashMapThreadLocal- 避免内存泄漏的缓存
-
调用
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;
程序可以从队列中取出这个引用对象,从而“得知”它指向的对象已被回收。
