在ReferenceQueue中的PhantomReference是否会阻止PhantomReference进行GC?

时间:2011-03-02 22:04:56

标签: java

我正在使用LWJGL库,不幸的是,每当我的场景图中的一个节点需要死时,我就需要释放纹理/ vbo缓冲区,我甚至不能使用finalize()方法来执行此操作,因为我可以' t保证它将在opengl lib期望的相同线程中执行。

所以我正在使用PhantomReferences。在我的场景图节点中,我将它放在构造函数中:

phantomReference = new ScenePhantomReference(this, Game.phantomReferenceQueue);
Game.phantomReferenceList.add(phantomReference);

正如您在第二行中所看到的,我已将phantomReference添加到主类中的列表中。我的逻辑是,当节点被解除引用时,phantomReference不会被垃圾收集,因为主类中仍有引用。

是否将其添加到需要的列表中?或者它是否会从GC中幸免(可能Game.phantomReferenceQueue会保留对它的引用?)。

这个测试很痛苦,我可以删除列表,但GC可能只是在phantomReference之前处理正在观察的对象,并使其看起来像列表是多余的,而实际上并非如此。我是偏执狂,任何不同的虚拟机实现或版本都可能决定反过来。

2 个答案:

答案 0 :(得分:4)

免责声明:我从未使用过PhantomReference。

但是,我确实阅读了this articlethis javadoc page,所以

  1. “是否将它添加到需要的列表中?[...](也许Game.phantomReferenceQueue会保留对它的引用?)”:根据javadoc页面:“引用队列,已注册的引用对象是在检测到适当的可达性更改后附加垃圾收集器。“所以我相信不,你不应该把它添加到List中,因为Queue会自动将它添加到垃圾收集器中。
  2. 我认为你必须改写一下你的问题 - 我不明白列表的用途,即我不理解最后一段。但是如果你正在使用列表以便知道phantomReference是否是gc'ed然后没有,那么你根本就不应该使用列表,那就是ReferenceQueue的用途。此外,列表将阻止幻像参考被gc'ed!
  3. 编辑:再次阅读帖子的标题。单独回答标题问题:不,因为PhantomReference在gc'ed之后进入ReferenceQueue - 所以根据定义它不能被停止为gc'ed。引用第一个链接:“这种引用的唯一用途[注意:他的意思是PhantomReference]跟踪它何时被引入ReferenceQueue,因为那时你知道它指向的对象已经死了”

    编辑#2:我还认为你的代码是错误的,你应该按如下方式初始化幻像引用(参见一个简单的例子here):

    PhantomReference scenePhantomRef = new PhantomReference(scene, phantomQueue);
    

    其中scene是您代码中的ScenePhantomReference(即您应该重构代码,以便ScenePhantomReference是名称,例如Scene,您将其实例化为scene然后使用上面的行来获取该对象PhantomReference的句柄。

答案 1 :(得分:0)

当引用的对象id为GC'd时,

PhantomReference对象被添加到队列中,而不是PhantomReference本身。 如果您没有向PhantomReference添加List,则不会引用PhantomReference对象,因此它会立即进行GC并且永远不会进入队列。