Have you ever used PhantomReference in any project?

The only thing I know about PhantomReference is

  • If you use the get() method, it will always return null , not the object. What is the use of this?
  • Using PhantomReference , you make sure that the object cannot be resurrected from the finalize method.

But what is the use of this concept / class?

Have you ever used this in any of your projects or do you have any example where we should use it?

+63
java reference
Oct 21 '09 at 6:36
source share
8 answers

I used PhantomReference in a simplified, highly specialized memory profile profile to monitor the creation and destruction of objects. I need them to monitor the destruction. But the approach is out of date. (This was written in 2004, targeting J2SE 1.4.) Professional profiling tools are much more powerful and reliable, and newer Java 5 features such as JMX or agents and JVMTI can also be used for this.

PhantomReference (always used with a reference queue) is superior to finalize , which has some problems and should therefore be avoided. Mainly make objects available again. This can be avoided by using the finalizer's guardian identifier (-> more in Effective Java). Thus, they are also a new finalization .

In addition, PhantomReference s

allows you to accurately determine when the object was deleted from memory. They are actually the only way to determine this. Usually this is not so useful, but it can come in handy in certain very specific circumstances, for example, manipulating large images: if you know for sure that the image must be garbage collected, you can wait until it actually appears. load the following image and therefore make the scary OutOfMemoryError less likely. (Quoted from enicholas .)

And as psd first wrote, Roedy Green has a good summary of links .

+40
Oct 21 '09 at 6:56
source share

A general explanation of the fact table from the Java glossary.

Which, of course, matches the PhantomReference documentation:

Phantom reference objects that are queued after the collector determines that their referents can be returned. Phantom links are most often used to plan attacks to prevent tampering in a more flexible way than is possible with the Java finalization mechanism.

And last but not least, all the details of gory (this is a good read): Java reference objects (or how I learned to stop worrying and love OutOfMemoryError) .

Happy coding. (But to answer the question, I only ever used WeakReferences.)

+18
Oct 21 '09 at 6:51
source share

I found a practical and useful use PhantomReference , which is org.apache.commons.io.FileCleaningTracker in a commons-io project. FileCleaningTracker will delete the physical file when its marker object is garbage collected.
Note the Tracker class, which extends the PhantomReference class.

+9
Jul 02 '12 at 18:01
source share

Great Phantom Explanation Using Links:

Phantom links are a safe way to find out if an object is deleted from memory. For example, consider an application that deals with large images. Suppose we want to load a large image into memory when the large image is already in memory, which is ready for garbage collection. In this case, we want to wait until the old file is assembled before loading a new one. Here the Phantom link is a flexible and secure fetch. The link to the old image will be highlighted in the ReferenceQueue after the completion of the old image object. After receiving this link, we can load the new image into memory.

+6
Jul 23 '13 at 12:43 on
source share

I used the PhantomReference in the unit test to make sure that the code under test didnโ€™t retain unreasonable references to any object. ( Source code )

 import static com.google.common.base.Preconditions.checkNotNull; import static org.fest.assertions.Assertions.assertThat; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import com.google.common.testing.GcFinalization; /** * Helps to test for memory leaks */ public final class MemoryTester { private MemoryTester() { } /** * A simple {@link PhantomReference} that can be used to assert that all references to it is * gone. */ public static final class FinalizationAwareObject extends PhantomReference<Object> { private final WeakReference<Object> weakReference; private FinalizationAwareObject(Object referent, ReferenceQueue<Object> referenceQueue) { super(checkNotNull(referent), referenceQueue); weakReference = new WeakReference<Object>(referent, referenceQueue); } /** * Runs a full {@link System#gc() GC} and asserts that the reference has been released * afterwards */ public void assertThatNoMoreReferencesToReferentIsKept() { String leakedObjectDescription = String.valueOf(weakReference.get()); GcFinalization.awaitFullGc(); assertThat(isEnqueued()).as("Object: " + leakedObjectDescription + " was leaked").isTrue(); } } /** * Creates a {@link FinalizationAwareObject} that will know if {@code referenceToKeepTrackOff} * has been garbage collected. Call * {@link FinalizationAwareObject#assertThatNoMoreReferencesToReferentIsKept()} when you expect * all references to {@code referenceToKeepTrackOff} be gone. */ public static FinalizationAwareObject createFinalizationAwareObject(Object referenceToKeepTrackOff) { return new FinalizationAwareObject(referenceToKeepTrackOff, new ReferenceQueue<Object>()); } } 

And test :

 @Test public void testThatHoldingOnToAnObjectIsTreatedAsALeak() throws Exception { Object holdMeTight = new String("Hold-me-tight"); FinalizationAwareObject finalizationAwareObject = MemoryTester.createFinalizationAwareObject(holdMeTight); try { finalizationAwareObject.assertThatNoMoreReferencesToReferentIsKept(); fail("holdMeTight was held but memory leak tester did not discover it"); } catch(AssertionError expected) { assertThat(expected).hasMessage("[Object: Hold-me-tight was leaked] expected:<[tru]e> but was:<[fals]e>"); } } 
+3
May 05 '13 at
source share

THIS SHOULD BE BETTER WITH JAVA 9!
Use java.util.Cleaner instead! (Or sun.misc.Cleaner on the older JRE)

Original post:




I found that using PhantomReferences has almost the same number of pitfalls as the finalizer methods (but with less problems when you get it right). I wrote a small solution (a very small basis for using PhantomReferences) for Java 8. It allows you to use lambda expressions as callbacks that will be executed after the object is deleted. You can register callbacks for internal resources that need to be closed. With this, I found a solution that works for me, as it makes it much more practical.

https://github.com/claudemartin/java-cleanup

Here is a small example showing how the callback is registered:

  class Foo implements Cleanup { //... public Foo() { //... this.registerCleanup((value) -> { try { // 'value' is 'this.resource' value.close(); } catch (Exception e) { logger.warning("closing resource failed", e); } }, this.resource); } 

And then there is an even simpler method of automatic closing, doing roughly the same thing as above:

 this.registerAutoClose(this.resource); 

To answer your questions:

[what uses it]

You cannot purify that which does not exist. But he might have resources that still exist, and they need to be cleaned up so that they can be removed.

But what is the use of this concept / class?

It is not necessary to do anything with any effect other than debugging / logging. Or maybe for statistics. I see that this is more like a notification service from the GC. You can also use it to remove aggregated data that becomes irrelevant after deleting an object (but there are probably better solutions for this). The examples often mention database connections that you need to close, but I donโ€™t see how such a good idea, how you could not work with transactions. The application framework will provide a much better solution for this.

Have you ever used this in any of your projects, or do you have any example where we should use it? Or this concept is made only for the interview point of view;)

I use it mainly for logging only. Therefore, I can track deleted items and see how the GC works and can be changed. Thus, I will not run critical code. If something needs to be closed, this should be done in a try-with-resource-statement. And I use it in unit tests to make sure that I have no memory leaks. Just like jontejj. But my solution is a little more general.

+3
May 29 '14 at 9:30
source share

PhantomReference is usually used, where PhantomReference is more suitable. This avoids certain problems associated with the possibility of resurrecting objects after the WeakReference is cleared / terminated by the garbage collector. Usually the difference does not matter, because people do not play stupid buggers.

Using PhantomReference tends to be a little more intrusive because you can't pretend that the get method works. You cannot, for example, write Phantom[Identity]HashMap .

+2
Oct 21 '09 at 10:06
source share

if you use the get () method, it will always return null, not an object. [then why use it]

Useful calling methods (not get() ) will be isEnqueued() or referenceQueue.remove() . You would call these methods to perform some of the actions that must be performed in the last round of garbage collection of the object.

The first time the object has its finalize() method, so you can also put closing hooks in there. However, as others have argued, there are probably more reliable ways to perform the cleanup or any action that needs to be taken to pre and post garbage collection or, more generally, after the facility has reached the end of its life.

+1
Aug 25 '16 at 12:00
source share



All Articles