Sponsored Link •
The garbage collector treats soft, weak, and phantom objects differently because each is intended to provide a different kind of service to the program. Soft references enable you to create in-memory caches that are sensitive to the overall memory needs of the program. Weak references enable you to create canonicalizing mappings, such as a hash table whose keys and values will be removed from the map if they become otherwise unreferenced by the program. Phantom references enable you to establish more flexible pre-mortem cleanup policies than are possible with finalizers.
To use the referent of a soft or weak reference, you invoke
get() on the reference object. If the reference hasn't been cleared, you'll get a strong reference to the referent, which you can then use in the usual way. If the reference has been cleared, you'll get
null back. If you invoke
get() on a phantom reference object, however, you'll always get
null back, even if the reference object hasn't yet been cleared. Because the phantom reachable state is only attained after an object passes through the resurrectable state, a phantom reference object provides no way to access to its referent. Invoking
get() on a phantom reference object always returns
null, even if the phantom reference hasn't yet been cleared, because if it returned a strong reference to the phantom reachable object, it would in effect resurrect the object. Thus, once an object reaches phantom reachability, it cannot be resurrected.
Virtual machine implementations are required to clear soft references before throwing
OutOfMemoryError, but are otherwise free to decide when or whether to clear them. Implementations are encouraged, however, to clear soft references only when the programs demand for memory exceeds the supply, to clear older soft references before newer ones, and to clear soft references that haven't been used recently before soft references that have been used recently.
Soft references enable you to cache in memory data that you can more slowly retrieve from an external source, such as a file, database, or network. So long as the virtual machine has enough memory to fit the softly referenced data on the heap together with all the strongly referenced data, the soft reference will in general be strong enough to keep the softly referenced data on the heap. If memory becomes scarce, however, the garbage collector may decide to clear the soft references and reclaim the space occupied by the softly referenced data. The next time the program needs to use that data, it will have to be reloaded from the external source. In the mean time, the virtual machine has more room to accommodate the strongly (and other softly) referenced memory needs of the program.
Weak references are similar to soft references, except that whereas the garbage collector is free to decide whether or not to clear soft references to softly reachable objects, it must clear weak references to weakly reachable objects as soon as it determines the objects are weakly reachable. Weak references enable you to create canonicalizing mappings from keys to values. The
java.util.WeakHashMap class uses weak references to provide just such a canonicalizing mapping. You can add key-value pairs to a
WeakHashMap instance via the
put() method, just like you can to an instance of any class that implements
java.util.Map. But inside the
WeakHashMap, the key objects are held via weak reference objects that are associated with a reference queue. If the garbage collector determines that a key object is weakly reachable, it will clear and enqueue any weak reference objects that refer to the key object. The next time the
WeakHashMap is accessed, it will poll the reference queue and extract all weak reference objects that the garbage collector put there. The
WeakHashMap will then remove from its mapping any key-value pairs for keys whose weak reference object showed up in the queue. Thus, if you add a key-value pair to a
WeakHashMap, it will remain there so long as the program doesn't explicitly remove it with the
remove() method and the garbage collector doesn't determine that the key object is weakly reachable.
Phantom reachability indicates that an object is ready for reclamation. When the garbage collector determines that the referent of a phantom reference object is phantom reachable, it appends the phantom reference object to its associated reference queue. (Unlike soft and weak reference objects, which can optionally be created without associating them with a reference queue, phantom reference objects cannot be instantiated without associating the reference object with a reference queue.) You can use the arrival of a phantom reference in a reference queue to trigger some action that you wish to take at the end of an object's lifetime. Because you can't get a strong reference to a phantom reachable object (the
get() method always returns
null), you won't be able to take any action that requires you to have access to the instance variables of the target. Once you have finished the pre-mortem cleanup actions for a phantom reachable object, you must invoke
clear() on the phantom reference objects that refer to it. Invoking
clear() on a phantom reference object is the coup de gras for its referent, sending the referent from the phantom reachable state to its final resting place: unreachability.