During garbage collection, immediately following the mark phase, these lists are processed in a specific order:
Soft references are collected if their referent is not marked (if they are not alive) and if #get() has not been called on the reference object within the previous 32 garbage collection cycles.
Weak and phantom references are always collected if their referent is not marked.
An element is eligible for processing if it is marked and has a non-null referent field. For each element on a list, GC determines if the reference object is eligible for processing and then if it is eligible for collection.
If an element is not eligible for processing, the reference object is removed from the reference list, resulting in it being freed during the sweep phase.
If an element is determined to be eligible for processing, GC must determine if it is eligible for collection.
The first criterion here is simple. Is the referent marked? If it is marked, the reference object is not eligible for collection. and GC moves onto the next element of the list.
If the referent is not marked, GC has a candidate for collection.
At this point the process differs for each reference type. Soft references are collected if their referent has not been marked for the previous 32 garbage collection cycles. This can be adujsted by -Xsoftrefthreshold option.
If there is a shortage of available storage, all soft references are cleared. All soft references are guaranteed to have been cleared before the OutOfMemoryError is thrown.
enqueue: To place an item in a queue.
referent: An instance of Refrence (subclasses) encapsulates a single reference to a particular object, called the referent.
Every reference object provides methods for getting and clearing the reference. Aside from the clearing operation reference objects are otherwise immutable, so no set operation is provided.
reference-object classes, which support a limited degree of interaction with the garbage collector.
Soft references are for implementing memory-sensitive caches.
Weak references are for implementing canonicalizing mappings that do not prevent their keys (or values) from being reclaimed.
Phantom references are for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.
Reference Queue to which registered reference objects are appended by the garbage collector after the appropriate reachability changes are detected.
Going from strongest to weakest, the different levels of reachability reflect the life cycle of an object. They are operationally defined as follows:
An object is strongly reachable if it can be reached by some thread without traversing any reference objects. A newly-created object is strongly reachable by the thread that created it.
An object is softly reachable if it is not strongly reachable but can be reached by traversing a soft reference.
An object is weakly reachable if it is neither strongly nor softly reachable but can be reached by traversing a weak reference. When the weak references to a weakly-reachable object are cleared, the object becomes eligible for finalization.
An object is phantom reachable if it is neither strongly, softly, nor weakly reachable, it has been finalized, and some phantom reference refers to it.
Finally, an object is unreachable, and therefore eligible for reclamation, when it is not reachable in any of the above ways.
A program may request to be notified of changes in an object’s reachability by registering an appropriate reference object with a reference queue at the time the reference object is created.
Some time after the garbage collector determines that the reachability of the referent has changed to the value corresponding to the type of the reference, it will add the reference to the associated queue. At this point, the reference is considered to be enqueued.
The program may remove references from a queue either by polling or by blocking until a reference becomes available. Reference queues are implemented by the ReferenceQueue class.
The relationship between a registered reference object and its queue is one-sided. That is, a queue does not keep track of the references that are registered with it. If a registered reference becomes unreachable itself, then it will never be enqueued. It is the responsibility of the program using reference objects to ensure that the objects remain reachable for as long as the program is interested in their referents.
While some programs will choose to dedicate a thread to removing reference objects from one or more queues and processing them, this is by no means necessary. A tactic that often works well is to examine a reference queue in the course of performing some other fairly-frequent action. For example, a hashtable that uses weak references to implement weak keys could poll its reference queue each time the table is accessed. This is how the WeakHashMap class works. Because the ReferenceQueue.poll method simply checks an internal data structure, this check will add little overhead to the hashtable access methods.
From java.lang.ref. Reference.java comments:
A Reference instance is in one of four possible internal states:
Active: Subject to special treatment by the garbage collector. Some time after the collector detects that the reachability of the referent has changed to the appropriate state, it changes the instance’s state to either Pending or Inactive, depending upon whether or not the instance was registered with a queue when it was created. In the former case it also adds the instance to the pending-Reference list. Newly-created instances are Active.