幽灵引用是Java中最弱的引用类型,不能阻止对象回收也无法获取对象实例,唯一用途是在对象被GC彻底回收后通过ReferenceQueue接收通知;必须绑定引用队列,GC后幽灵引用入队,需轮询队列执行事后清理。

幽灵引用(PhantomReference)是 Java 中最弱的一种引用类型,它**不能阻止对象被回收,也不能通过它获取到对象实例**,唯一用途就是——在对象被垃圾回收器真正清理后,收到一个“通知”。它和垃圾回收(GC)的配合,本质上是借助 ReferenceQueue 实现的异步回收状态跟踪。
幽灵引用必须配合引用队列使用
幽灵引用的构造方法强制要求传入一个 ReferenceQueue。当 GC 发现某个对象只被幽灵引用持有时,会先将该幽灵引用加入关联的队列中,再真正回收对象内存。注意:此时对象已不可达,也无法被复活(finalizer 已被禁用,且幽灵引用无法 get())。
- 创建时必须绑定队列:
new PhantomReference(obj, queue) - 对象被回收后,引用本身(不是原对象)会被入队,可通过
queue.poll()或queue.remove()检测 - 入队时机是 GC 完成“清除”阶段之后,但不保证立即发生(取决于 GC 线程调度)
典型使用模式:资源清理 + 状态标记
由于无法访问原对象,幽灵引用常用于执行“事后清理”,比如释放堆外内存、关闭文件句柄、记录回收日志等。同时可结合外部状态标识(如 Map 记录),实现对回收状态的跟踪。
- 在创建幽灵引用时,把关键上下文(如 ID、时间戳、资源句柄)存入外部结构(如
ConcurrentHashMap<PhantomReference<?>, Info>) - 后台线程轮询引用队列,取出幽灵引用后,查表获取对应信息,执行清理并移除记录
- 这样就能知道“哪个对象已被回收”,实现轻量级生命周期监控
与软引用、弱引用的关键区别
幽灵引用不参与“可达性判断”的中间阶段,它不延迟 GC,也不提供对象访问能力,因此更安全、更可控。
立即学习“Java免费学习笔记(深入)”;
- 软引用:适合缓存,JVM 内存不足时才回收
- 弱引用:GC 时只要不可达就回收,
get()可能返回 null,仍可短暂访问对象 - 幽灵引用:对象进入 F-Queue 后立即被清除,
get()始终返回 null;只有入队才算“确认回收完成”
注意事项与常见陷阱
幽灵引用容易误用,实际效果高度依赖正确使用队列和及时轮询。
- 幽灵引用本身不会自动清除,必须手动从队列中取走,否则队列会堆积,导致内存泄漏(引用对象本身占内存)
- 没有轮询线程或轮询不及时,就无法感知回收事件,状态跟踪就失效
- 不要试图在 finalize() 中操作幽灵引用(Java 9+ 已弃用 finalize,且幽灵引用与之无关)
- 避免在引用队列处理逻辑中做耗时操作,否则阻塞轮询,影响其他回收通知


















