Java 101: Trash talk, Part 2

The Reference Objects API allows programs to interact with the garbage collector

1 2 3 Page 3
Page 3 of 3

There is a second difference between SoftReference, WeakReference, and PhantomReference objects. If either a SoftReference or a WeakReference object has an associated reference queue, the garbage collector places a reference to that object on the reference queue sometime after it clears the referent's soft or weak reference. In contrast, the garbage collector places a reference to a PhantomReference object onto the queue before the phantom reference clears. Also, the program, not the garbage collector, clears the phantom reference by calling PhantomReference's clear() method, inherited from the Reference class. Until the phantom reference clears, the garbage collector does not reclaim the referent. Once the phantom reference clears, however, the referent moves from the phantomly reachable state to the unreachable state. Game over for the referent!

Note
By now, you know a call to get() on a SoftReference or WeakReference object, whose reference returns from a call to poll() or remove(), cannot return a referent's reference. That's not possible because the garbage collector clears the referent's soft or weak reference before placing the SoftReference or WeakReference object's reference on the queue. However, because the garbage collector does not clear the referent's phantom reference, you would expect get() to return a reference to that referent. Instead, get() returns null to prevent the referent from being resurrected.

Listing 3 demonstrates phantom references:

Listing 3. PhantomReferenceDemo.java

// PhantomReferenceDemo.java
import java.lang.ref.*;
class Employee
{
   private String name;
   Employee (String name)
   {
      this.name = name;
   }
   public void finalize () throws Throwable
   {
      System.out.println ("finalizing " + name);
      super.finalize ();
   }
}
class PhantomReferenceDemo
{
   public static void main (String [] args)
   {
      // Create an Employee object that is strongly reachable from e.
      Employee e = new Employee ("John Doe");
      // Create a ReferenceQueue object that is strongly reachable from q.
      ReferenceQueue q = new ReferenceQueue ();
      // Create a PhantomReference object that is strongly reachable from
      // pr. The PhantomReference object encapsulates the Employee object
      // (so the Employee object is phantomly reachable from the
      // PhantomReference object), and associates the ReferenceQueue object,
      // referenced by q, with the PhantomReference object.
      PhantomReference pr = new PhantomReference (e, q);
      // Remove the only strong reference to the Employee object.
      e = null;
      // Poll reference queue until PhantomReference object arrives.
      Reference r;
      while ((r = q.poll ()) == null)
      {
         System.out.println ("Polling reference queue");
         // Suggest that the garbage collector should run.
         System.gc ();
      }
      System.out.println ("Employee referent in phantom-reachable state.");
      // Clear the PhantomReference object's phantom reference, so that
      // the Employee referent enters the unreachable state.
      pr.clear ();
      // Clear the strong reference to the PhantomReference object, so the
      // PhantomReference object is eligible for garbage collection. (The
      // same could be done for the ReferenceQueue and Reference objects --
      // referenced by q and r, respectively.) Although not necessary in
      // this trivial program, you might consider doing such clearing in a
      // long-running loop, so that objects not needed can be collected.
      pr = null;
   }
}

When run, PhantomReferenceDemo produces output similar to the following:

Polling reference queue
finalizing John Doe
Polling reference queue
Employee referent in phantom-reachable state.

The garbage collector has not yet run when the first Polling reference queue message appears. The first call to System.gc (); causes the JVM to try to run the garbage collector. It runs and executes Employee's finalize() method, which prints finalizing John Doe. The second Polling reference queue message indicates that a second call is made to System.gc ();. That call causes the garbage collector to move the Employee referent from the resurrectable state to the phantomly reachable state.

A close look at Listing 3 shows a pr.clear (); method call. That method call clears the phantom reference to the Employee referent in the PhantomReference object. That referent now enters the unreachable state, and the garbage collector can reclaim its memory the next time it runs.

Review

The Reference Objects API gives your programs limited interaction with the garbage collector through the SoftReference, WeakReference, and PhantomReference classes. Objects created from SoftReference contain soft references to their referents. You can use soft references to manage image and other memory-sensitive caches. Objects that you create from WeakReference contain weak references to their referents. You use weak references to obtain notification when significant objects are no longer strongly reachable. Finally, PhantomReference objects contain phantom references to their referents. You can use phantom references to perform post-finalization cleanup on the referents.

I encourage you to email me with any questions you might have involving either this or any previous article's material. (Please, keep such questions relevant to material discussed in this column's articles.) Your questions and my answers will appear in the relevant study guides.

In next month's article, you will learn about nested classes.

Jeff Friesen has been involved with computers for the past 20 years. He holds a degree in computer science and has worked with many computer languages. Jeff has also taught introductory Java programming at the college level. In addition to writing for JavaWorld, he has written his own Java book for beginners -- Java 2 By Example, Second Edition (Que Publishing, 2001; ISBN: 0789725932) -- and helped write Special Edition Using Java 2 Platform (Que Publishing, 2001; ISBN: 0789720183). Jeff goes by the nickname Java Jeff (or JavaJeff). To see what he's working on, check out his Website at http://www.javajeff.com.

Learn more about this topic

1 2 3 Page 3
Page 3 of 3