Previous | Next | Trail Map | Reference Objects | All About Reference Objects

Weakly Reachable

An object is weakly reachable when the garbage collector finds no strong or soft references, but at least one path to the object with a weak reference. Weakly reachable objects are finalized some time after their weak references have been cleared. The only real difference between a soft reference and a weak reference is that the garbage collector uses algorithms to decide whether or not to reclaim a softly reachable object, but always reclaims a weakly reachable object.

Weak references work well in applications that, for example, need to associate extra data with an unchangeable object, such as a thread the application did not create. If you make a weak reference to the thread with a reference queue, your program can be notified when the thread is no longer strongly reachable. Upon receiving this notification, your program can perform any required cleanup of the associated data object.

To make the Thread object weakly reachable, its strong reference must be set to null. After the garbage collector clears the weak reference to the thread, it places the weak reference on the queue. When the program removes the reference from the queue, it can then remove the corresponding hash map entry, and thereby, allow the data object to be reclaimed.

The following code example stores an object and some extra data in a hash map. The object is referenced by a weak reference object that was created with a reference queue. This is a very simple code example to illustrate the points discussed in this trail. In a real application, the data would be associated with the object well after the object is created; otherwise, you could keep the data in a subclass of the object instead of using a weak reference.

After the object becomes weakly reachable, the garbage collector clears the weak reference and places it in the reference queue. The code queries the reference queue for the weak reference, and upon finding the weak reference, sets the reference to the extra data to null so the extra data is garbage-collected after the object is.

An important point in this example is that the object can be reached from the stack through two paths: one path goes through the weak reference and the other goes through the hash map. The object does not become weakly reachable until the reference to it in the hash map is null. It is not enough to just set the object to null.

Here is the source code for the WeakObj.java class.


Note: This code works on Solaris, and will be replaced with one that works on all platforms.

import java.lang.ref.*;
import java.util.*;

public class WeakObj {

 public static void main(String[] args) {
  try {
    ReferenceQueue aReferenceQueue = new ReferenceQueue();
    Object anObject = new Object();
    WeakReference ref = new WeakReference(anObject,
                                        aReferenceQueue);
    String extraData = new String("Extra Data");
    HashMap aHashMap = new HashMap();;

//Associate extraData (value) with anObject (key) in aHashMap
    aHashMap.put(anObject, extraData);

//Check that a reference to an object was created
    System.out.println("*** created ref to some object");
    System.out.println();
    System.out.println("contents of ref: " + ref.get());
    system.out.println();


//Check whether the reference Object is enqueued
    System.out.println("ref.isEnqueued(): " + ref.isEnqueued());
    System.out.println();

//Clear the strong reference to anObject
    anObject = null;

//Clear the strong reference to extraData
    if(anObject == null){
      extraData = null;
    }

//Run the garbage collector, and
//Check the Reference object's referent
    System.out.println("*** running gc...");
    System.gc();
    System.out.println();
    System.out.println("contents of ref: " + ref.get());
    System.out.println();


//Check whether the Reference Object is enqueued
    System.out.println("ref.isEnqueued(): " + ref.isEnqueued());
    System.out.println();

//Enqueue the Reference Object. This method returns false
//if the Reference Object is already enqueued.
    System.out.println("enqueued="+ref.enqueue());

  } catch (Exception e) {
    System.err.println("An exception occurred:");
    e.printStackTrace();
  }
 }
}


Previous | Next | Trail Map | Reference Objects | All About Reference Objects