6

根据链接https://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html,只有当对象从内存中物理移除并且WeakReferences在最终确定或垃圾收集之前入队时, PhantomReferences才会入队实际发生了。

不同之处在于排队发生的确切时间。一旦弱引用指向的对象变得弱可达,弱引用就会被排队。这是在最终确定或垃圾收集实际发生之前;理论上,对象甚至可以通过非正统的 finalize() 方法“复活”,但 WeakReference 将保持死态。仅当对象从内存中物理删除时,PhantomReferences 才会入队,并且 get() 方法始终返回 null 专门用于防止您能够“复活”几乎死掉的对象。

而根据http://www.ibm.com/developerworks/library/j-refs/,在释放堆对象之前将PhantomReference添加到其ReferenceQueue中,并且在完成或垃圾回收之后将WeakReferences添加到其 ReferenceQueue 中。

与软引用和弱引用不同,PhantomReference 在堆对象被释放之前被添加到它的 ReferenceQueue 中。(请记住,所有 PhantomReference 对象都必须使用关联的 ReferenceQueue 创建。)这允许在回收堆对象之前采取行动。

当堆对象的 finalize() 方法运行并释放其内存时,WeakReference 对象将添加到其 ReferenceQueue(如果存在)。

我很困惑。哪一个是正确的?

基本上我想知道关于引用队列的弱引用和幻像引用之间的区别?

4

1 回答 1

9

在参考队列上:

WeakReference 和 PhantomReference 都将在它们的引用对象(被引用对象)不是强可达之后加入队列,如果它们在创建时注册了非空引用队列。

在通过入队之前,WeakReference 清除(无效)引用字段以使引用完全无法访问。当 WeakReference 被清除时,应用程序不能再 get() 所指对象。这意味着,稍后当 WeakReference 入队时,get() 返回 null。WeakReference 在创建时可能没有注册的引用队列。应用程序可以通过 get()-ing 来检测其所指对象是否不可访问。有时,当应用程序不想显式管理弱引用时,引用队列可以方便地管理它们。

在通过入队之前,PhantomReference 不会清除引用字段。当它入队时,引用对象仍然被 PhantomReference 引用。仅当应用程序将引用队列出列后,引用对象才会被显式清除。如果应用程序没有清除它,则引用对象会一直保留在那里,直到它和它的 PhantomReference 一起被回收。在任何情况下,PhantomReference 上的 get() 总是返回 null,即使它没有被清除。因此,应用程序无法通过 get()-ing 来检测其所指对象是否不可访问。应用程序只能通过检查 PhantomReference 是否排队来检测。出于这个原因,必须创建一个 PhantomReference 并注册一个引用队列;否则,它是没有用的。

定稿时:

当 WeakReference 被清除时,所指对象变得不可访问。如果所指对象有一个非默认终结器,它会被终结,因此被复活。如果引用对象没有非默认终结器,则它会被 GC 回收。换句话说,WeakReferences 在最终确定之前被处理。

如果 PhantomReference 的参照物只能通过 PhantomReference 到达,则它还不是幻影可到达的。只有在最终确定后仍然如此(只能通过 PhantomReference 访问)时,它才是幻影可达的。换句话说,PhantomReferences 是在完成后处理的。只有那些没有通过终结而复活的参照物是幻影可达的,因此它们肯定会死。但是从那时起 PhantomReference 将被排队,那些指示物还没有死。仅当应用程序稍后清除 PhantomReference 或 PhantomReference 本身变得无法访问时(然后 PhantomReference 及其所指对象一起被回收),它们才变得可回收。

于 2015-10-16T03:13:01.660 回答