Java中PhantomReference和ReferenceQueue的使用方法和工作机制
PhantomReference简介
PhantomReference是JDK提供的一种引用,可直译为虚引用
首先,PhantomReference引用的get方法永远返回null
其次,只被这种虚引用所引用的对象,如果没有其他额外的有效引用的话,在执行GC垃圾回收时就会被认定为是垃圾了(但不会立刻被回收)
PhantomReference的作用是帮我们跟踪下相关对象的回收情况(比如Netty就有利用PhantomReference帮开发者诊断内存泄露问题),或者做一些清理工作(类似finalize)
ReferenceQueue简介
PhantomReference的构造函数要求我们除了传入对象引用外,还要传一个ReferenceQueue进去,即实例化一个PhantomReference的时候,需要额外关联一个ReferenceQueue
这个ReferenceQueue就是用来协助我们跟踪被PhantomReference关联到的对象的
不可达与虚可达
需要注意的是,并不是创建一个PhantomReference和ReferenceQueue就一定能跟踪被GC的对象了,这里要区分两个状态,它们是不可达和虚可达
不可达:一个对象没有被有效的引用所指向,且指向该对象的PhantomReference(如果有的话)也成了垃圾
虚可达:一个对象虽然没有被有效的引用所指向,但被PhantomReference引用所关联,且关联它的PhantomReference对象被其他有效引用指到了(不算垃圾了)
对于不可达的对象,JVM会直接回收掉它,不会触发跟踪相关的事了,而如果是虚可达的话,JVM就会把它判定成垃圾,但却不去回收,而是交到关联的ReferenceQueue里面去,让我们开发人员自行处理,我们必须在处理它之后,把这个虚引用干掉,让这个被处理的对象从虚可达转到不可达,最终让它被回收掉
工作机制
当一个被PhantomReference关联过的对象是虚可达时,垃圾收集器会把这些对象放到我们构造PhantomReference时关联的ReferenceQueue里面,然后我们可以去ReferenceQueue里取出这些对象,从而知道哪些对象在GC时被回收了或做一些额外的清理工作
示例代码
public class App {
private static ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
private static List<PhantomReference> references = new ArrayList<>();
private static List<DataObj> dataObjs = new ArrayList<>();
public static void main(String[] args) throws Exception {
for (int i = 0; i < 32; ++i) {
DataObj obj = new DataObj();
PhantomReference<Object> phantomReference = new PhantomReference<>(obj, referenceQueue);
references.add(phantomReference);
dataObjs.add(obj);
}
// 设置为null 让相关对象编程虚可达 被GC特殊对待一下
dataObjs = null;
System.gc();
// 直接在主线程看
Reference<?> reference = null;
while ((reference = referenceQueue.poll()) != null) {
System.out.println(reference);
reference.clear();
}
}
}
class DataObj {
}
需要说明的是,由于System.gc()不保证一定触发gc,所以要看到效果需要多执行几次
总结
PhantomReference和ReferenceQueue可以帮我们跟踪那些被GC的对象,我们用PhantomReference来关联对象,并绑定一个ReferenceQueue,当对象是虚可达的时候,就会被放到ReferenceQueue里,然后我们可以发现它并进行处理,最后要注意的是,处理完之后,要把对应的PhantomReference干掉,让对象成为不可达,最终再被GC回收,不然可能造成内存泄露哦!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)