So as soon as one Refernce becomes enqueued I know its componentID and send a call to the client to free that Object.

As I understand both Weak- and PhantomReferences are suited for this task, so where is the benefit from using Phantom- or WeakReferences for this task? Which Referencetype has higher overhead?
Is there a large GC-penality when using Weak/Phantom-References in general?

Any whats the idea behind PhantomReference's specified behaviour to prevent an object from beeing freed if a PhantomReference refers to it, although it can't be reached anyway. Isn't this just unescessary overhead?

Reply viewing options

The Javadoc information on References is not very intuitive and doesn't say much about how they are implemented. In the Sun JDK 1.4+, SoftReferences are usually left longer on the heap, and only reclaimed when heap memory (in which ever space) is getting low. Also the Sun JVM is biased towards clearing the least mostly recently used references first. Weak references on the other hand are cleared more eagerly and tend to be cleared at the next GC cycle after becoming weakly reachable. All three types of reference increase the GC overhead a little since they require extra work to determine when they can be dropped, but I'm not aware of any difference between them.

Two excellent reads on the uses and differences of Weak and SoftReferences can be found here:

The difference between Phantom refs. and soft and weak refs. is the order in which things happen. With Soft and Weak refs. the GC will clear the reference FIRST, i.e. the referent becomes reclaimable and then at some point in the near future will enqueue the reference object itself onto the ReferenceQueue (if one was specified). With Phantom refs. the object is enqueued first, but NOT cleared (hence the reason that Phantoms MUST have a ReferenceQueue). The performance penalty between Weak and Phantom should be almost unmeasurable.

Since you are wanting to use this method purely for GC feedback on the objects, then PhantomReference is the one to use. WeakReferences are better suited when a reference to an object only needs to be maintained in a map or similar as long as it is needed by some other part of the program. The PhantomReference will appear on its queue when the object it was referencing is truly dead. However, as pointed out in the doc for that class. [b]"An object that is reachable via phantom references will remain so until all such references are cleared or themselves become unreachable"[/b]. This means that when you retrieve the reference from a ReferenceQueue, it is imperative to call the clear() method on that reference as you call the client to release it.

An article by Ethan Nicholas provides an even better explanation of PhantomReferences than the above articles: Uses of References. Out of the three articles I've cited, this is the most pragmatic.

Finally, the idea behind the PhantomReference preventing an object from being reclaimed though it can't be reached is a bit strange. As both you, Nicholas and others have commented the use cases of PhantomReferences are very limited without extending the class with some form of identifier as you have here. The primary use case is exactly what you require here: notification of reclaimation. The reason the get() method always returns null is to prevent part of the mess with finalizers in that objects could be resurrected.With PhantomReferences, this is impossible since the referent can't be obtained.

Before your post I was biased a bit in favour of WeakReferences because I already knew them well and thought the "reclaim-only-if-cleared" behaviour made me believe there is overhead (because at least 2gc cycles are needed to reclaim it whereas WeakReferences can be collected with a single gc-cycle, right?), however the fact that its not possible to resurrect an object already enqued is a big win for my use-cae.

The base-framework already works fine now and I am able to program using an swing-like api as if the gui would be running on the server. Wonderful ^^

Sorry that I am nerving soo much but this topic interrests me quite a lot.

If in the first cycle an object is found which is phantom-reachable only, why can it be released - if it can only released if the Phatom-Reference is cleared?
I thought it would work this way:
1.) GC-cycle, phantom-reachable object is identified
2.) Phantom-Reference is enqued in the ReferenceQueue
3.) User-code can now call clear() on the Phantom-Reference
4.) GC can free the space used by the object?

Yet another example of the stupid patent system abuse. Well anyway I guess that clears that one up for good. So if I understand that post correctly, once a soft or weak reference has been cleared and enqueued, its still possible for that object to re-appear due to resurrection in an overridden finalizer method. However, as mentioned elsewhere, a Reference type that has been cleared will always remain so, even in the presence of resurrection. However, with a Phantom, the object has already been finalized if necessary (objects that don't override finalize() can't be resurrected the standard way, and the language spec. states that an object can ONLY be finalized once), so it absolutely impossible for a enqueued phantom ref. to come back.

Thanks a lot for the very interresting talk and the tons of information about PhantomReferences.
Although I knew about the fact than an object could be resurrected, I never thought about how this could affect my framework but it indeed could - a programmer could access a handle on the server whereas the counterpart could have been freed already because its server-counterpart was enqueued already.

In a few months I'll release my project as free software, maybe it will be useful for somebody ;)
Thanks for all the help and patience :-)