Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 5 of 7
ReferenceQueue q = new ReferenceQueue (); SoftReference sr = new SoftReference (new Employee (), q);
After the garbage collector clears the referent's soft reference, it appends SoftReference's strong reference to the reference queue that q references. The addition of SoftReference happens when the garbage collector calls Reference's enqueue() method (behind the scenes). Your program can either poll the reference queue, by calling ReferenceQueue's poll() method, or block, by calling ReferenceQueue's no-argument remove() method, until the reference arrives on the queue. At that point, your program can either stop polling or automatically unblock.
Because the poll() and remove() methods return a SoftReference object reference (through the Reference return types), you discover which soft reference cleared; you can then modify your cache as appropriate.
To demonstrate reference queues and soft references, I have created a SoftReferenceDemo application, which chooses to call poll() instead of remove() to increase the likelihood of garbage collection. If the application was to call remove(), the garbage collector might not run -- because the application doesn't constantly create objects and nullify their references.
Hence, the application would remain blocked. Examine SoftReferenceDemo's source code in Listing 1:
Listing 1. SoftReferenceDemo.java
// SoftReferenceDemo.java
import java.lang.ref.*;
class Employee
{
private String name;
Employee (String name)
{
this.name = name;
}
public String toString ()
{
return name;
}
}
class SoftReferenceDemo
{
public static void main (String [] args)
{
// Create two Employee objects that are strongly reachable from e1
// and e2.
Employee e1 = new Employee ("John Doe");
Employee e2 = new Employee ("Jane Doe");
// Create a ReferenceQueue object that is strongly reachable from q.
ReferenceQueue q = new ReferenceQueue ();
// Create a SoftReference array with room for two references to
// SoftReference objects. The array is strongly reachable from sr.
SoftReference [] sr = new SoftReference [2];
// Assign a SoftReference object to each array element. That object
// is strongly reachable from that element. Each SoftReference object
// encapsulates an Employee object that is referenced by e1 or e2 (so
// the Employee object is softly reachable from the SoftReference
// object), and associates the ReferenceQueue object, referenced by
// q, with the SoftReference object.
sr [0] = new SoftReference (e1, q);
sr [1] = new SoftReference (e2, q);
// Remove the only strong references to the Employee objects.
e1 = null;
e2 = null;
// Poll reference queue until SoftReference object arrives.
Reference r;
while ((r = q.poll ()) == null)
{
System.out.println ("Polling reference queue");
// Suggest that the garbage collector should run.
System.gc ();
}
// Identify the SoftReference object whose soft reference was
// cleared, and print an appropriate message.
if (r == sr [0])
System.out.println ("John Doe Employee object's soft reference " +
"cleared");
else
System.out.println ("Jane Doe Employee object's soft reference " +
"cleared");
// Attempt to retrieve a reference to the Employee object.
Employee e = (Employee) r.get ();
// e will always be null because soft references are cleared before
// references to their containing SoftReference objects are queued
// onto a reference queue.
if (e != null)
System.out.println (e.toString ());
}
}
When run, SoftReferenceDemo might poll the reference queue for a short time or a long time. The following output shows one SoftReferenceDemo invocation:
Polling reference queue Polling reference queue Polling reference queue Polling reference queue Polling reference queue Polling reference queue Polling reference queue Polling reference queue Polling reference queue Polling reference queue Polling reference queue Polling reference queue Polling reference queue Jane Doe Employee object's soft reference cleared
SoftReferenceDemo calls System.gc (); (in a loop) to encourage the garbage collector to run. Eventually, at least on my platform, the garbage collector runs, and
at least one soft reference clears. After that soft reference clears, a reference to the soft reference's enclosing SoftReference object appends to the reference queue. By comparing the returned reference with each sr array element reference, the program code can determine which Employee referent had its soft reference cleared. We can now recreate the Employee object, if so desired.
The weakly reachable state manifests itself in Java through the WeakReference class. When you initialize a WeakReference object, you store a referent's reference in that object. The object contains a weak reference to the referent, and the referent is weakly reachable if there are no other references, apart from weak references, to that
referent. If heap memory is running low, the garbage collector locates weakly reachable objects and clears their weak references
-- by calling WeakReference's inherited clear() method. Assuming no other references point to those referents, the referents enter either the resurrectable state or the
unreachable state. Assuming the referents enter the resurrectable state, the garbage collector calls their finalize() methods. If those methods do not make the referents reachable, the referents become unreachable, and the garbage collector
can reclaim their memory.
| Note |
|---|
| The primary difference between soft references and weak references is that the garbage collector might clear a soft reference but always clears a weak reference. |
To create a WeakReference object, pass a reference to a referent in one of two constructors. For example, the following code fragment creates a ReferenceQueue object and uses the WeakReference(Object referent, ReferenceQueue q) constructor to create a WeakReference object (that encapsulates a Vehicle referent) and associate WeakReference with the reference queue:
ReferenceQueue q = new ReferenceQueue (); WeakReference wr = new WeakReference (new Vehicle (), q);
Use weak references to obtain notification when significant objects are no longer strongly reachable. For example, suppose
you create an application that simulates a company. That application periodically creates Employee objects. For each object, the application also creates an employee-specific Benefits object. During the simulation, employees eventually retire and their Employee objects are made eligible for garbage collection. Because it would prove detrimental for a Benefits object to hang around after its associated Employee object is garbage collected, the program should notice when Employee is no longer strongly reachable.