java中通过referencequeue配合weakreference可在对象被gc回收后立即获知该事件,原理是gc清除referent后将弱引用实例入队,程序需主动poll/remove队列来感知回收。

Java 中通过 ReferenceQueue 配合弱引用(WeakReference)可以**在对象被垃圾回收器回收后,立即获知这一事件**。这不是“监听”或回调机制,而是利用 GC 回收弱引用时自动将该引用实例入队的特性,由程序主动轮询或处理队列来感知回收发生。
弱引用 + 引用队列的基本协作流程
当你创建一个 WeakReference 并关联一个 ReferenceQueue 时,JVM 在执行 GC 发现其 referent(被引用对象)不可达后,会:
- 清除该弱引用内部的 referent(即设为
null) - 将这个
WeakReference实例本身添加到构造时传入的ReferenceQueue中
之后,你的代码只需从队列中 poll() 或 remove() 就能拿到已被回收的弱引用对象,从而知道“某个对象刚刚被回收了”。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
典型用法:注册并轮询引用队列
以下是一个简洁可靠的操作模式:
Object obj = new Object();
ReferenceQueue<object> queue = new ReferenceQueue();
WeakReference<object> ref = new WeakReference(obj, queue);
// 此时 obj 仍可达,ref.get() != null
obj = null; // 切断强引用
System.gc(); // 建议 GC(仅用于演示,实际不保证立即触发)
// 主动检查队列:若 ref 已入队,说明 referent 被回收
Reference extends Object> cleaned = queue.poll();
if (cleaned != null) {
System.out.println("对象已被回收,对应的弱引用:" + cleaned);
}
</object></object>
注意关键细节
-
队列中存放的是引用对象本身(如
WeakReference),不是被引用的对象;被引用对象此时已为null,不可再访问 -
queue.poll()是非阻塞的,返回null表示暂无回收事件;queue.remove()会阻塞直到有引用入队(适合后台清理线程) - 必须在构造弱引用时显式传入队列,否则 GC 不会将其入队
- 软引用(
SoftReference)和虚引用(PhantomReference)也支持引用队列,但语义不同:虚引用必须配合队列使用,且其get()永远返回null
实用场景举例
这种机制常用于实现资源清理、缓存失效、监听对象生命周期等轻量级需求,例如:
- 自定义缓存中,当 key 是弱引用时,可通过队列及时移除对应缓存条目
- 为某些临时资源(如本地内存映射、JNI 句柄)维护清理钩子,在弱引用入队后释放非堆资源
- 调试或监控工具中跟踪对象存活情况,统计“有多少对象在上次 GC 后被回收”
不复杂但容易忽略:它依赖你主动检查队列,而不是自动触发回调。所以通常需搭配单独线程或定时任务持续消费队列。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










