The Java Reference Classes

Now that you understand the concepts, let's reconsider the code. All of the reference types mentioned in the previous section appear in the java.lang.ref package.

Reference Classes

The majority of the java.lang.ref package is comprised of reference classes. These classes are the implementation of the actual references covered in the previous section, with one exception. There is no StrongReference class. Since a strong reference is a normal Java variable, there is no need for extra implementation. However, the other types of references all descend from the base class Reference.

java.lang.ref.Reference

The Reference class is an abstract class that defines the functionality of the reference classes. The implementation classes—WeakReference, SoftReference, and PhantomReference—implement the functionality of the base class. All of these classes have four methods that they inherit from Reference:


clear( )

Clears the referent, which causes the referent in this reference object to be set to null without affecting the object itself. I have never found a use for this method, since there is no way to reset the referent after it has been cleared.


enqueue( )

Registers a reference with a ReferenceQueue. This allows the user to receive updates about the status of the object in memory. A reference will be placed in a reference queue at garbage-collection time only if it was registered with that queue. If it succeeds in registering the reference, the method will return true; otherwise, it will return false. Keep in mind that a reference can be registered only with one queue at a time, and if you call this method on a reference that is already registered with a queue, the object will be unregistered from the previous queue. If you call enqueue( ) with a null argument, you will unregister the object.


isEnqueued( )

Tests to see whether the reference has been queued.


get( )

Returns a strong reference to the referent object to the user. If you execute this after the reference has been queued or the garbage collection has been completed, null will always be returned.

There is no way to set the referent object via a method call. In fact, the referent can be set only when the reference object is constructed. At that time, you can also register the reference with a queue. Construct a reference object with the following code:

Object obj = new Object( );
WeakReference ref = new WeakReference(obj);


This code will create a new weak reference to the object obj. This reference won't be registered with any queue at creation time, so you won't be able to know when the object is garbage collected. You can always register it with a new queue later by calling the enqueue( ) method.

Screenshot

I will show why you may want to create a reference without queueing it in .


Alternatively, you could construct the reference, as in the following code:

ReferenceQueue clearedObjects = new ReferenceQueue( );
SoftReference ref2 = new SoftReference(obj, clearedObjects);


This code will create a new reference to obj and simultaneously queue it in the given queue. Note that you can create multiple reference objects of multiple types to the same referent. In this case, there is a weak reference and a soft reference to the same object. In garbage collection, the strong reference takes precedence. Therefore, if all strong references to obj are gone, the soft reference will hold the obj in memory until the heap needs more memory.

java.lang.ref.WeakReference

This class implements the weak-reference paradigm. All of its methods, and even its code, are identical to Reference. The code inside the reference class does all of the work; this class merely provides a façade to the abstract class.

java.lang.ref.SoftReference

This class implements the soft-reference paradigm. It allows the base class to keep the referents in memory until the memory is low. To do this, the garbage collector timestamps the object so that the oldest soft references are purged first. Of course, this implementation is all under-the-hood. On the outside, there is no difference between this class and a WeakReference.

java.lang.ref.PhantomReference

This class implements the phantom-reference paradigm. Like SoftReference, the implementation of this is all under the hood. However, the phantom reference's get( ) method will always return null. Once you create this type of reference, you are hinting to the garbage collector to tell you when it is completely dead. For this to happen, there must be no way to retrieve a strong reference.

Reference Queues

The java.lang.ref.ReferenceQueue class implements reference queues, which are repositories for garbage-collection events. A reference queue consists of the following methods:


poll( )

This checks the reference queue to see whether there are any reference objects in the queue. If it finds one, it returns the first reference in the queue. This reference is left on the queue.


remove( )

This removes the first reference on the queue and returns it to the caller. If there are no references on the queue, it returns null.


remove(long timeout)

This performs the same job as the remove( ) method, but it will wait up to the specified number of milliseconds for a reference object to arrive in the queue before returning null or a reference.

Its important not to forget that the reference queue is modified by the garbage collector directly. Therefore, it is impossible to determine when the references will arrive in the queue. If you destroy all strong references to an object, the related Reference object may not arrive in the queue until much later. Since garbage collection runs periodically, your reference won't be queued until the next garbage-collection pass. If you want to ensure that the reference arrives quickly, use remove(long) and set the timeout as a value that is longer than the duration of each garbage-collection pass. Consult your virtual-machine documentation for more information.

      
Comments