Java中ReferenceQueue通过接收被GC回收的弱/软/虚引用对象实现监控,JVM在回收后自动将对应引用入队,需主动poll/remove检测;虚引用最适配,因不阻止回收、get()恒返回null,且能精确感知对象进入finalization阶段。

Java 中结合 ReferenceQueue 监控被回收的对象,核心是利用引用队列接收被 JVM 回收的软引用、弱引用或虚引用对象——注意:只有 WeakReference、SoftReference 和 PhantomReference 支持关联引用队列,而 StrongReference 不行。
为什么 ReferenceQueue 能“监控”回收?
当 GC 发现某个对象只被弱/软/虚引用持有时,会根据引用类型策略决定是否回收该对象。一旦回收,JVM 会自动将对应的引用对象(如 WeakReference 实例)加入其注册的 ReferenceQueue。这不是回调,而是“入队”,你需要主动轮询或监听队列变化。
基本使用步骤(以 WeakReference 为例)
- 创建一个
ReferenceQueue实例,作为回收通知的“消息通道” - 创建
WeakReference<T>(或PhantomReference),把目标对象和队列一起传入构造函数 - 在合适时机(如后台线程中)调用
queue.remove()或queue.poll()检查是否有引用入队 - 一旦拿到出队的引用对象,就能知道“原来那个对象已被回收”,可触发清理逻辑(如关闭资源、清除缓存条目等)
虚引用(PhantomReference)是最适合监控回收的类型
因为虚引用不会阻止对象回收,且 get() 方法永远返回 null,避免误用原对象;它必须配合 ReferenceQueue 使用,是唯一能**精确感知对象已进入 finalization 阶段且即将被彻底回收**的机制。常用于堆外内存管理、资源泄漏检测等场景。
示例关键代码:
立即学习“Java免费学习笔记(深入)”;
ReferenceQueue<Object> queue = new ReferenceQueue<>();
Object obj = new Object();
PhantomReference<Object> ref = new PhantomReference<>(obj, queue);
// 后续让 obj 不再被强引用
obj = null;
System.gc(); // 建议仅用于演示,生产环境不依赖
// 稍后检查队列
if (queue.poll() != null) {
System.out.println("对象已被回收");
}
注意事项和常见陷阱
-
ReferenceQueue是线程安全的,但remove()会阻塞,建议用poll()避免卡住线程 - 不要在
finalize()中恢复对象引用(已废弃且不可靠),虚引用才是现代替代方案 - 弱引用可能在 GC 后立刻入队,也可能延迟(取决于 GC 策略),不能假设实时性
- 记得在引用对象出作用域前显式置为
null,否则引用对象本身可能阻碍队列清理


















