2

I haven't used PhantomReferences. There seems to be very few good examples of real-world use.

When a phantom shows up in your queue, how do you know which object it is/was? The get() method appears to be useless. According to the JavaDoc,

Because the referent of a phantom reference is always inaccessible, this method always returns null.

I think that unless your object is a singleton, you always want to use a subclass of PhantomReference, in which you place whatever mementos you need in order to understand what died.

Is this correct, or did I miss something?

Is this also true for SoftReferences? For WeakReferences?

Links to relevant examples of usage would be great.

Ed Staub
  • 15,480
  • 3
  • 61
  • 91
  • 1
    the first and last time i came across phantom references was during my degree, it was my supervisor's opinion that they were pretty much useless. – lynks Oct 08 '11 at 01:47
  • I wonder if he'd thought of subclassing the reference. – Ed Staub Oct 08 '11 at 02:33
  • @lynks, they are not useless, you can create your own finalizer-alike with them. Subclassing w/ some runnable (either impl. or referred) it's a common way. Alternatively you can use identity map Phantom->Runnable. `sun.misc.Clearner` was introduced in java 1.4 in favor of finalization and all DirectBuffers use it. – bestsss Oct 08 '11 at 06:55

2 Answers2

1

Your question has caused me to look into it a little more, and I found this very well written explanation and examples of all the reference types. He even talks about some (tenuous) uses of phantom references.

http://weblogs.java.net/blog/2006/05/04/understanding-weak-references

lynks
  • 5,599
  • 6
  • 23
  • 42
1

I think that unless your object is a singleton, you always want to use a subclass of PhantomReference, in which you place whatever mementos you need in order to understand what died.

You could also use a Map<Reference<?>, SomeMetadataClassOrInterface> to recover whatever metadata you need. Since ReferenceQueue<T> returns a Reference<T>, you either have to cast it to whatever subclass of PhantomReference you expect, or let a Map<> do it for you.

For what it's worth, it looks like using PhantomReferences puts some burden on you:

Unlike soft and weak references, phantom references are not automatically cleared by the garbage collector as they are enqueued. An object that is reachable via phantom references will remain so until all such references are cleared or themselves become unreachable.

so you'd have to clear() the references yourself in order for memory to be reclaimed. (why there is usefulness in having to do so vs. letting the JVM do this for you is beyond me)

Jason S
  • 184,598
  • 164
  • 608
  • 970
  • 1
    Thanks, Jason. The only good scenario I can think of is one where some kind of JNI-implemented asynchronous data source is writing into the referenced object, and must be told to stand down before the memory is recycled. In this case, a simple forgot-to-dispose() bug could result in memory corruption without a mechanism like Phantom. A different way to express it is that this is a better alternative to finalize(). Make sense? – Ed Staub Oct 10 '11 at 17:16
  • ahhh... never thought of the case where JNI-encapsulated code is using memory allocated by the JVM. Other than that, there doesn't seem to be any reason for garbage collection of particular memory blocks to be delayed. – Jason S Oct 10 '11 at 17:22