Have you ever used PhantomReference in any project?

Viewed 25377

The only thing I know about PhantomReference is,

  • If you use its get() method, it will always return null and not the object. What's the use of it?
  • By using PhantomReference, you make it sure that the object cannot be resurrected from finalize method.

But what is the use of this concept/class?

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

11 Answers

I used it in the early days of Android. Back them a BitmapDrawable had an underlying Bitmap that used memory that was not allocated in the Java Heap space, which meant that you were using memory, but the JVM didn't feel the memory pressure. The symptom was the app would crash by running out of memory, but you'd never find that your finalizer was called (or that there hadn't been a garbage collection sweep at all).

So I created a subclass of PhantomReference that had a hard reference to the Bitmap (class variable). The PhantomReference itself pointed to the BitmapDrawable.

When the phantom reference would come off the queue indicating that the BitmapDrawable was no longer reachable, I'd call the release method on the Bitmap which released the memory that was outside of the vm heap space.

It worked great, it more or less completely removed the out of memory failures that occurred because of that weird memory model on early Android.

Android later changed the memory model to load bitmaps into the JVM heap, btw, because you actually want your vm to feel memory pressure if the app is running out of memory. It was definitely a "Black Diamond" situation to have to release the memory like this and I doubt most app developers realized that Garbage Collection wasn't going to help them because the memory was outside the view of the Garbage Collector. They probably just viewed it as an Android bug.

I found another practical use of PhantomReferences in LeakDetector class of Jetty.

Jetty uses LeakDetector class to detect if the client code acquires a resource but never releases it and the LeakDetector class uses the PhantomReferences for this purpose.

Here is a generic example of using it: In this case, for some Swing code in a vector editor, where it's easy to create tens of thousands of AffineTransform instances inside the paint loop, when they are easily recycled and reused, and this showed itself to be a significant bottleneck in profiling. I've used the same pattern to reuse CharBuffer instances when processing log files line-by line. Basically the pattern is: You have some data structure which is expensive to create, and it is one you can completely reset the state on, rather than create a new one every time. So, you create a PhantomReference subclass that strongly references the object you want to recycle and reuse, whose referent is a thing that could be referencing the object; to track when it is safe to recycle an object, you either

  1. Return a facade for the object, that implements the same interface or something close enough (e.g. a CharSequence implementation that wraps a CharBuffer), and use that as the referent of your PhantomReference or
  2. Callers pass you a reference to themselves and so you can recycle an object when the caller goes out of scope

In other words, the pattern here you're asking the queue to tell you when every object that could know about some cached thing is gone, so you can make it available for reuse to another caller.

Related