src/java.base/share/classes/java/lang/ref/Reference.java
changeset 50277 f84ae8aa5d88
parent 49973 e3653598e3b0
child 52427 3c6aa484536c
equal deleted inserted replaced
50276:6a5a8ed5e475 50277:f84ae8aa5d88
    41  * @since    1.2
    41  * @since    1.2
    42  */
    42  */
    43 
    43 
    44 public abstract class Reference<T> {
    44 public abstract class Reference<T> {
    45 
    45 
    46     /* A Reference instance is in one of four possible internal states:
    46     /* The state of a Reference object is characterized by two attributes.  It
    47      *
    47      * may be either "active", "pending", or "inactive".  It may also be
    48      *     Active: Subject to special treatment by the garbage collector.  Some
    48      * either "registered", "enqueued", "dequeued", or "unregistered".
    49      *     time after the collector detects that the reachability of the
    49      *
    50      *     referent has changed to the appropriate state, it changes the
    50      *   Active: Subject to special treatment by the garbage collector.  Some
    51      *     instance's state to either Pending or Inactive, depending upon
    51      *   time after the collector detects that the reachability of the
    52      *     whether or not the instance was registered with a queue when it was
    52      *   referent has changed to the appropriate state, the collector
    53      *     created.  In the former case it also adds the instance to the
    53      *   "notifies" the reference, changing the state to either "pending" or
    54      *     pending-Reference list.  Newly-created instances are Active.
    54      *   "inactive".
    55      *
    55      *   referent != null; discovered = null, or in GC discovered list.
    56      *     Pending: An element of the pending-Reference list, waiting to be
    56      *
    57      *     enqueued by the Reference-handler thread.  Unregistered instances
    57      *   Pending: An element of the pending-Reference list, waiting to be
    58      *     are never in this state.
    58      *   processed by the ReferenceHandler thread.  The pending-Reference
    59      *
    59      *   list is linked through the discovered fields of references in the
    60      *     Enqueued: An element of the queue with which the instance was
    60      *   list.
    61      *     registered when it was created.  When an instance is removed from
    61      *   referent = null; discovered = next element in pending-Reference list.
    62      *     its ReferenceQueue, it is made Inactive.  Unregistered instances are
    62      *
    63      *     never in this state.
    63      *   Inactive: Neither Active nor Pending.
    64      *
    64      *   referent = null.
    65      *     Inactive: Nothing more to do.  Once an instance becomes Inactive its
    65      *
    66      *     state will never change again.
    66      *   Registered: Associated with a queue when created, and not yet added
    67      *
    67      *   to the queue.
    68      * The state is encoded in the queue and next fields as follows:
    68      *   queue = the associated queue.
    69      *
    69      *
    70      *     Active: queue = ReferenceQueue with which instance is registered, or
    70      *   Enqueued: Added to the associated queue, and not yet removed.
    71      *     ReferenceQueue.NULL if it was not registered with a queue; next =
    71      *   queue = ReferenceQueue.ENQUEUE; next = next entry in list, or this to
    72      *     null.
    72      *   indicate end of list.
    73      *
    73      *
    74      *     Pending: queue = ReferenceQueue with which instance is registered;
    74      *   Dequeued: Added to the associated queue and then removed.
    75      *     next = this
    75      *   queue = ReferenceQueue.NULL; next = this.
    76      *
    76      *
    77      *     Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
    77      *   Unregistered: Not associated with a queue when created.
    78      *     in queue, or this if at end of list.
    78      *   queue = ReferenceQueue.NULL.
    79      *
    79      *
    80      *     Inactive: queue = ReferenceQueue.NULL; next = this.
    80      * The collector only needs to examine the referent field and the
    81      *
    81      * discovered field to determine whether a (non-FinalReference) Reference
    82      * With this scheme the collector need only examine the next field in order
    82      * object needs special treatment.  If the referent is non-null and not
    83      * to determine whether a Reference instance requires special treatment: If
    83      * known to be live, then it may need to be discovered for possible later
    84      * the next field is null then the instance is active; if it is non-null,
    84      * notification.  But if the discovered field is non-null, then it has
    85      * then the collector should treat the instance normally.
    85      * already been discovered.
    86      *
    86      *
    87      * To ensure that a concurrent collector can discover active Reference
    87      * FinalReference (which exists to support finalization) differs from
    88      * objects without interfering with application threads that may apply
    88      * other references, because a FinalReference is not cleared when
    89      * the enqueue() method to those objects, collectors should link
    89      * notified.  The referent being null or not cannot be used to distinguish
    90      * discovered objects through the discovered field. The discovered
    90      * between the active state and pending or inactive states.  However,
    91      * field is also used for linking Reference objects in the pending list.
    91      * FinalReferences do not support enqueue().  Instead, the next field of a
       
    92      * FinalReference object is set to "this" when it is added to the
       
    93      * pending-Reference list.  The use of "this" as the value of next in the
       
    94      * enqueued and dequeued states maintains the non-active state.  An
       
    95      * additional check that the next field is null is required to determine
       
    96      * that a FinalReference object is active.
       
    97      *
       
    98      * Initial states:
       
    99      *   [active/registered]
       
   100      *   [active/unregistered] [1]
       
   101      *
       
   102      * Transitions:
       
   103      *                            clear
       
   104      *   [active/registered]     ------->   [inactive/registered]
       
   105      *          |                                 |
       
   106      *          |                                 | enqueue [2]
       
   107      *          | GC              enqueue [2]     |
       
   108      *          |                -----------------|
       
   109      *          |                                 |
       
   110      *          v                                 |
       
   111      *   [pending/registered]    ---              v
       
   112      *          |                   | ReferenceHandler
       
   113      *          | enqueue [2]       |--->   [inactive/enqueued]
       
   114      *          v                   |             |
       
   115      *   [pending/enqueued]      ---              |
       
   116      *          |                                 | poll/remove
       
   117      *          | poll/remove                     |
       
   118      *          |                                 |
       
   119      *          v            ReferenceHandler     v
       
   120      *   [pending/dequeued]      ------>    [inactive/dequeued]
       
   121      *
       
   122      *
       
   123      *                           clear/enqueue/GC [3]
       
   124      *   [active/unregistered]   ------
       
   125      *          |                      |
       
   126      *          | GC                   |
       
   127      *          |                      |--> [inactive/unregistered]
       
   128      *          v                      |
       
   129      *   [pending/unregistered]  ------
       
   130      *                           ReferenceHandler
       
   131      *
       
   132      * Terminal states:
       
   133      *   [inactive/dequeued]
       
   134      *   [inactive/unregistered]
       
   135      *
       
   136      * Unreachable states (because enqueue also clears):
       
   137      *   [active/enqeued]
       
   138      *   [active/dequeued]
       
   139      *
       
   140      * [1] Unregistered is not permitted for FinalReferences.
       
   141      *
       
   142      * [2] These transitions are not possible for FinalReferences, making
       
   143      * [pending/enqueued] and [pending/dequeued] unreachable, and
       
   144      * [inactive/registered] terminal.
       
   145      *
       
   146      * [3] The garbage collector may directly transition a Reference
       
   147      * from [active/unregistered] to [inactive/unregistered],
       
   148      * bypassing the pending-Reference list.
    92      */
   149      */
    93 
   150 
    94     private T referent;         /* Treated specially by GC */
   151     private T referent;         /* Treated specially by GC */
    95 
   152 
       
   153     /* The queue this reference gets enqueued to by GC notification or by
       
   154      * calling enqueue().
       
   155      *
       
   156      * When registered: the queue with which this reference is registered.
       
   157      *        enqueued: ReferenceQueue.ENQUEUE
       
   158      *        dequeued: ReferenceQueue.NULL
       
   159      *    unregistered: ReferenceQueue.NULL
       
   160      */
    96     volatile ReferenceQueue<? super T> queue;
   161     volatile ReferenceQueue<? super T> queue;
    97 
   162 
    98     /* When active:   NULL
   163     /* The link in a ReferenceQueue's list of Reference objects.
    99      *     pending:   this
   164      *
   100      *    Enqueued:   next reference in queue (or this if last)
   165      * When registered: null
   101      *    Inactive:   this
   166      *        enqueued: next element in queue (or this if last)
       
   167      *        dequeued: this (marking FinalReferences as inactive)
       
   168      *    unregistered: null
   102      */
   169      */
   103     @SuppressWarnings("rawtypes")
   170     @SuppressWarnings("rawtypes")
   104     volatile Reference next;
   171     volatile Reference next;
   105 
   172 
   106     /* When active:   next element in a discovered reference list maintained by GC (or this if last)
   173     /* Used by the garbage collector to accumulate Reference objects that need
   107      *     pending:   next element in the pending list (or null if last)
   174      * to be revisited in order to decide whether they should be notified.
   108      *   otherwise:   NULL
   175      * Also used as the link in the pending-Reference list.  The discovered
   109      */
   176      * field and the next field are distinct to allow the enqueue() method to
   110     private transient Reference<T> discovered;  /* used by VM */
   177      * be applied to a Reference object while it is either in the
       
   178      * pending-Reference list or in the garbage collector's discovered set.
       
   179      *
       
   180      * When active: null or next element in a discovered reference list
       
   181      *              maintained by the GC (or this if last)
       
   182      *     pending: next element in the pending-Reference list (null if last)
       
   183      *    inactive: null
       
   184      */
       
   185     private transient Reference<T> discovered;
   111 
   186 
   112 
   187 
   113     /* High-priority thread to enqueue pending References
   188     /* High-priority thread to enqueue pending References
   114      */
   189      */
   115     private static class ReferenceHandler extends Thread {
   190     private static class ReferenceHandler extends Thread {
   139             }
   214             }
   140         }
   215         }
   141     }
   216     }
   142 
   217 
   143     /*
   218     /*
   144      * Atomically get and clear (set to null) the VM's pending list.
   219      * Atomically get and clear (set to null) the VM's pending-Reference list.
   145      */
   220      */
   146     private static native Reference<Object> getAndClearReferencePendingList();
   221     private static native Reference<Object> getAndClearReferencePendingList();
   147 
   222 
   148     /*
   223     /*
   149      * Test whether the VM's pending list contains any entries.
   224      * Test whether the VM's pending-Reference list contains any entries.
   150      */
   225      */
   151     private static native boolean hasReferencePendingList();
   226     private static native boolean hasReferencePendingList();
   152 
   227 
   153     /*
   228     /*
   154      * Wait until the VM's pending list may be non-null.
   229      * Wait until the VM's pending-Reference list may be non-null.
   155      */
   230      */
   156     private static native void waitForReferencePendingList();
   231     private static native void waitForReferencePendingList();
   157 
   232 
   158     private static final Object processPendingLock = new Object();
   233     private static final Object processPendingLock = new Object();
   159     private static boolean processPendingActive = false;
   234     private static boolean processPendingActive = false;