搜索了很多关于幻影参考的内容,但无法找到它的实际用法。从逻辑上讲,get()方法在Phantom References
的情况下返回null答案 0 :(得分:8)
您可以按照blog:
进行操作PhantomReferences有什么用?我只知道两个严重的情况 对于他们:首先,他们允许您确定一个对象的确切时间 被从记忆中删除。事实上,它们是唯一确定的方法 那。这通常没那么有用,但可能会派上用场 某些特定情况,如操纵大图像:如果 你肯定知道图像应该是垃圾收集的,你可以 在尝试加载下一张图片之前,请等到它 因此不太可能使可怕的OutOfMemoryError。
其次,PhantomReferences避免了一个基本问题 finalization:finalize()方法可以通过创建“复活”对象 新的强烈参考。那么,你说什么?嗯,问题是 现在必须确定覆盖finalize()的对象 垃圾在至少两个单独的垃圾收集周期中才能实现 被收集。当第一个循环确定它是垃圾时,它 有资格完成定稿。因为(苗条,但是 不幸的是真实的)物体被“复活”的可能性 在最终确定期间,垃圾收集器必须在之前再次运行 实际上可以删除对象。因为最终确定可能不会 及时发生了,任意数量的垃圾 在对象等待时可能发生了收集周期 定稿。这可能意味着实际清理工作严重延误 垃圾对象,这就是为什么你甚至可以获得OutOfMemoryErrors 大部分堆都是垃圾。
另请阅读:The Mysterious Phantom Reference
请考虑以下代码。
public class Foo { private String bar; public Foo(String bar) { this.bar = bar; } public String foo() { return bar; } }
因此,在对象被完全取消引用后,让我们说 应用程序我想要一些如何调用foo()。这是我的一些代码 预计可以通过一个小问题来完成这项工作。
// initialize ReferenceQueue<Foo> queue = new ReferenceQueue<Foo>(); ArrayList< PhantomReference<Foo>> list=new ArrayList<PhantomReference<Foo>>(); for ( int i = 0; i < 10; i++) { Foo o = new Foo( Integer.toOctalString( i)); list.add(new PhantomReference<Foo>(o, queue)); } // make sure the garbage collector does it’s magic System.gc(); // lets see what we’ve got Reference<? extends Foo> referenceFromQueue; for ( PhantomReference<Foo> reference : list) System.out.println(reference.isEnqueued()); while ( (referenceFromQueue = queue.poll()) != null) { System.out.println(referenceFromQueue.get()); referenceFromQueue.clear(); }
PhantomReference采用Foo和ReferenceQueue的实例。以来 没有句柄留给Foo,它应该立即死亡。接下来,告诉 要收集的VM,因为它没有足够的堆来触发a 收藏自然。我要问的第一件事就是 PhantomReference是;你被列入了吗?在这种情况下的答案 将是真的。接下来我要求队列参考,但你可以 看,调用get()总是返回null。关于唯一的解决方案 有意义的是包装你想要交互的资源或对象 在PhantomReference的子类中。
public class FinalizeStuff<Foo> extends PhantomReference<Foo> { public FinalizeStuff(Foo foo, ReferenceQueue<? super Foo> queue) { super(foo, queue); } public void bar() { System.out.println("foobar is finalizing resources"); } }
在这种情况下,我不打算将Foo包装在子类中 似乎违反了PhantomReference的精神。相反,我要去 包装与Foo相关的资源并与之交互。现在我能 这样做。
// initialize ReferenceQueue<Foo> queue = new ReferenceQueue<Foo>(); ArrayList< FinalizeStuff<Foo>> list = new ArrayList<FinalizeStuff<Foo>>(); ArrayList<Foo> foobar = new ArrayList<Foo>(); for ( int i = 0; i < 10; i++) { Foo o = new Foo( Integer.toOctalString( i)); foobar.add(o); list.add(new FinalizeStuff<Foo>(o, queue)); } // release all references to Foo and make sure the garbage collector does it’s magic foobar = null; System.gc(); // should be enqueued Reference<? extends Foo> referenceFromQueue; for ( PhantomReference<Foo> reference : list) { System.out.println(reference.isEnqueued()); } // now we can call bar to do what ever it is we need done while ( (referenceFromQueue = queue.poll()) != null) { ((FinalizeStuff)referenceFromQueue).bar(); referenceFromQueue.clear(); }