ReferenceQueue的含义
我试图了解课堂 ReferenceQueue
它是的可选构造函数参数
SoftReference
和
WeakReference
这也是的强制性参数PhantomReference
。
根据我已阅读的信息,我可以写一些论文
a)对于PhantomReference方法,get始终返回null
b)
1. gc检测到可以从内存中删除
该对象2.
当我们从队列中调用clear或link到引用的引用时,引用了放置到ReferenceQueue的对象,因为无法访问并且gc看到了3.
finalize方法调用
4。
可用内存
1. gc检测到可以从内存中删除对象
2. finalize方法调用
3.空闲内存
4.对放入队列的对象的引用
- 什么时候可以将第二个参数传递给
XXXReference
构造函数? - 我可以获得哪些帮助?
- 为什么
PhantomReference
没有构造函数ReferenceQueue
呢? - 是什么原因让ReferenceQuee的get方法始终返回null?
回答:
也许以下程序会有所帮助:
public class SimpleGCExample { public static void main(String[] args) throws InterruptedException {
ReferenceQueue<Object> queue=new ReferenceQueue<>();
SimpleGCExample e = new SimpleGCExample();
Reference<Object> pRef=new PhantomReference<>(e, queue),
wRef=new WeakReference<>(e, queue);
e = null;
for(int count=0, collected=0; collected<2; ) {
Reference ref=queue.remove(100);
if(ref==null) {
System.gc();
count++;
}
else {
collected++;
System.out.println((ref==wRef? "weak": "phantom")
+" reference enqueued after "+count+" gc polls");
}
}
}
@Override
protected void finalize() throws Throwable {
System.out.println("finalizing the object in "+Thread.currentThread());
Thread.sleep(100);
System.out.println("done finalizing.");
}
}
在我的系统上,它会打印
weak reference enqueued after 1 gc pollsfinalizing the object in Thread[Finalizer,8,system]
done finalizing.
phantom reference enqueued after 2 gc polls
要么
finalizing the object in Thread[Finalizer,8,system]weak reference enqueued after 1 gc polls
done finalizing.
phantom reference enqueued after 2 gc polls
由于多线程,前两个消息的顺序有时会有所不同。有时,幻象引用被报告在三个轮询之后加入队列,这表明它花费了超过指定的100毫秒的时间。
关键是
- 开始完成时,软引用和弱引用被清除并排入队列
- 幻象引用 在 完成 后 排队,假设该对象没有泄漏该
finalize
方法,否则在对象再次变得不可访问之后将它们排队 - (非平凡的)
finalize()
方法的存在导致需要至少一个额外的垃圾收集周期来检测对象不可达或幻像可达
由于所有对象中超过99%的对象不需要完成,因此强烈建议所有JVM供应商检测何时finalize()
未被覆盖或“琐碎”,即空方法或单独super.finalize()
调用。在这些情况下,应该省略最终确定步骤。通过删除finalize()
上面示例中的方法,您可以轻松检查此优化是否在JVM中发生。然后打印
weak reference enqueued after 1 gc pollsphantom reference enqueued after 1 gc polls
由于两者都立即入队并以任意顺序检索,因此这两个消息的顺序可能会有所不同。但是它们总是在一个gc周期后都被排入队列。
值得注意的是,幻像引用不会自动清除,这意味着它需要另一个垃圾回收周期,直到对象的内存真正可以重用为止,因此上面的示例至少需要三个周期(使用非平凡finalize()
方法),两个不使用。Java
9将对此进行更改,自动清除幻像引用,因此在上面的示例中,将需要两个周期进行最终确定,而一个周期直到真正可以回收内存为止。好吧,准确地说,在这个简单的示例中,对象的内存将永远不会被回收,因为程序会在此之前终止。
上面的代码还演示了Reference
API的预期用例之一。我们可以使用它来检测对象的可访问性何时在我们的完全控制下的代码中更改,例如,使用main
方法内的循环。相反,finalize()
可以在任意时间由不同的未指定线程调用。该示例还显示,您可以从参考对象中提取信息,而无需使用该get()
方法。
实际应用程序经常使用引用类的子类向它们添加更多信息。这就是WeakHashMap.Entry
扩展WeakReference
和记住哈希码和值的过程。清理可以在常规映射操作中完成,不需要任何线程同步。finalize()
除了地图实现无法将finalize()
方法推入键类之外,使用方法是不可能的。
这意味着“比完成更灵活”一词。
该WeakHashMap
演示了get()
方法是有用的。只要尚未收集密钥,就会将其报告为在地图中,并且可以在遍历所有密钥或条目时进行检索。
该PhantomReference.get()
方法已被覆盖以始终返回,null
以防止应用程序可以重新占用已排队引用的引用。这是“虚拟引用不会自动清除”规则的直接结果。该规则本身令人怀疑,其初衷是在黑暗中。虽然该规则将在下一个Java版本中进行更改,但是恐怕get()
它将继续返回null
向后兼容。
以上是 ReferenceQueue的含义 的全部内容, 来源链接: utcz.com/qa/407615.html