< prev index next >

src/java.base/share/classes/java/lang/ref/Reference.java

Print this page
rev 50110 : [mq]: mandy_1


  31 import jdk.internal.misc.SharedSecrets;
  32 import jdk.internal.ref.Cleaner;
  33 
  34 /**
  35  * Abstract base class for reference objects.  This class defines the
  36  * operations common to all reference objects.  Because reference objects are
  37  * implemented in close cooperation with the garbage collector, this class may
  38  * not be subclassed directly.
  39  *
  40  * @author   Mark Reinhold
  41  * @since    1.2
  42  */
  43 
  44 public abstract class Reference<T> {
  45 
  46     /* The state of a Reference object is characterized by two attributes.  It
  47      * may be either "active", "pending", or "inactive".  It may also be
  48      * either "registered", "enqueued", "dequeued", or "unregistered".
  49      *
  50      * Active: Subject to special treatment by the garbage collector.  Some
  51      * time after the collector detects that the reachability of the referent
  52      * has changed to the appropriate state, the collector "notifies" the
  53      * reference, changing the state to either "pending" or "inactive".

  54      * referent != null; discovered = null, or in GC discovered list.
  55      *
  56      * Pending: An element of the pending-Reference list, waiting to be
  57      * processed by the Reference-handler thread.  The pending-Reference list
  58      * is linked through the discovered fields of references in the list.

  59      * referent = null; discovered = next element in pending-Reference list.
  60      *
  61      * Inactive: Neither Active nor Pending.
  62      * referent = null.
  63      *
  64      * Registered: Associated with a queue when created, and not yet added to
  65      * the queue.
  66      * queue = the associated queue.
  67      *
  68      * Enqueued: Added to the associated queue, and not yet removed.
  69      * queue = ReferenceQueue.ENQUEUE; next = next entry in list, or this to
  70      * indicate end of list.
  71      *
  72      * Dequeued: Added to the associated queue and then removed.
  73      * queue = ReferenceQueue.NULL; next = this.
  74      *
  75      * Unregistered: Not associated with a queue when created.
  76      * queue = ReferenceQueue.NULL.
  77      *
  78      * The collector only needs to examine the referent field and the
  79      * discovered field to determine whether a normal (non-FinalReference)
  80      * Reference object needs special treatment.  If the referent is non-null
  81      * and not known to be live, then it may need to be discovered for
  82      * possible later notification.  But if the discovered field is non-null,
  83      * then either (1) it has already been discovered, or (2) it is in the
  84      * pending list.
  85      *
  86      * FinalReference (which exists to support finalization, which was
  87      * deprecated in JDK 9) differs from normal references, because a
  88      * FinalReference is not cleared when notified.  The referent being null
  89      * or not cannot be used to distinguish between the active state and
  90      * pending or inactive states.  However, FinalReferences do not support
  91      * enqueue().  Instead, the next field of a FinalReference object is set
  92      * to "this" when it is added to the pending list.  The use of "this"
  93      * as the value of next in the enqueued and dequeued states maintains the
  94      * non-active state.  An additional check that the next field is null is
  95      * required to determine that a FinalReference object is active.
  96      *
  97      * Initial states:
  98      *   active/registered
  99      *   active/unregistered [1]
 100      *
 101      * Transitions:
 102      *   active/registered    -> pending/registered    - GC
 103      *                        -> inactive/registered   - clear
 104      *                        -> inactive/enqueued     - enqueue [2]
 105      *   pending/registered   -> pending/enqueued      - enqueue [2]
 106      *                        -> inactive/enqueued     - pending list processing
 107      *   pending/enqueued     -> inactive/enqueued     - pending list processing
 108      *                        -> pending/dequeued      - poll/remove
 109      *   pending/dequeued     -> inactive/dequeued     - pending list processing
 110      *   inactive/registered  -> inactive/enqueued     - enqueue [2]
 111      *   inactive/enqueued    -> inactive/dequeued     - poll/remove
 112      *
 113      *   active/unregistered  -> pending/unregistered  - GC
 114      *                        -> inactive/unregistered - GC, clear, enqueue
 115      *   pending/unregistered -> inactive/unregistered - pending list processing














 116      *
 117      * Terminal states:
 118      *   inactive/dequeued
 119      *   inactive/unregistered
 120      *
 121      * Unreachable states (because enqueue also clears):
 122      *   active/enqeued
 123      *   active/dequeued
 124      *
 125      * [1] Unregistered is not permitted for FinalReferences.
 126      *
 127      * [2] These transitions are not possible for FinalReferences, making
 128      * pending/enqueued and pending/dequeued unreachable, and
 129      * inactive/registered terminal.




 130      */
 131 
 132     private T referent;         /* Treated specially by GC */
 133 
 134     /* The queue this reference gets enqueued to by GC notification or by
 135      * calling enqueue().
 136      *
 137      * When registered: the queue with which this reference is registered.
 138      *        enqueued: ReferenceQueue.ENQUEUE
 139      *        dequeued: ReferenceQueue.NULL
 140      *    unregistered: ReferenceQueue.NULL
 141      */
 142     volatile ReferenceQueue<? super T> queue;
 143 
 144     /* The link in a ReferenceQueue's list of Reference objects.
 145      *
 146      * When registered: null
 147      *        enqueued: next element in queue (or this if last)
 148      *        dequeued: this (marking FinalReferences as inactive)
 149      *    unregistered: null


 180 
 181         static {
 182             // pre-load and initialize Cleaner class so that we don't
 183             // get into trouble later in the run loop if there's
 184             // memory shortage while loading/initializing it lazily.
 185             ensureClassInitialized(Cleaner.class);
 186         }
 187 
 188         ReferenceHandler(ThreadGroup g, String name) {
 189             super(g, null, name, 0, false);
 190         }
 191 
 192         public void run() {
 193             while (true) {
 194                 processPendingReferences();
 195             }
 196         }
 197     }
 198 
 199     /*
 200      * Atomically get and clear (set to null) the VM's pending list.
 201      */
 202     private static native Reference<Object> getAndClearReferencePendingList();
 203 
 204     /*
 205      * Test whether the VM's pending list contains any entries.
 206      */
 207     private static native boolean hasReferencePendingList();
 208 
 209     /*
 210      * Wait until the VM's pending list may be non-null.
 211      */
 212     private static native void waitForReferencePendingList();
 213 
 214     private static final Object processPendingLock = new Object();
 215     private static boolean processPendingActive = false;
 216 
 217     private static void processPendingReferences() {
 218         // Only the singleton reference processing thread calls
 219         // waitForReferencePendingList() and getAndClearReferencePendingList().
 220         // These are separate operations to avoid a race with other threads
 221         // that are calling waitForReferenceProcessing().
 222         waitForReferencePendingList();
 223         Reference<Object> pendingList;
 224         synchronized (processPendingLock) {
 225             pendingList = getAndClearReferencePendingList();
 226             processPendingActive = true;
 227         }
 228         while (pendingList != null) {
 229             Reference<Object> ref = pendingList;
 230             pendingList = ref.discovered;




  31 import jdk.internal.misc.SharedSecrets;
  32 import jdk.internal.ref.Cleaner;
  33 
  34 /**
  35  * Abstract base class for reference objects.  This class defines the
  36  * operations common to all reference objects.  Because reference objects are
  37  * implemented in close cooperation with the garbage collector, this class may
  38  * not be subclassed directly.
  39  *
  40  * @author   Mark Reinhold
  41  * @since    1.2
  42  */
  43 
  44 public abstract class Reference<T> {
  45 
  46     /* The state of a Reference object is characterized by two attributes.  It
  47      * may be either "active", "pending", or "inactive".  It may also be
  48      * either "registered", "enqueued", "dequeued", or "unregistered".
  49      *
  50      *   Active: Subject to special treatment by the garbage collector.  Some
  51      *   time after the collector detects that the reachability of the
  52      *   referent has changed to the appropriate state, the collector
  53      *   "notifies" the reference, changing the state to either "pending" or
  54      *   "inactive".
  55      *   referent != null; discovered = null, or in GC discovered list.
  56      *
  57      *   Pending: An element of the pending-Reference list, waiting to be
  58      *   processed by the ReferenceHandler thread.  The pending-Reference
  59      *   list is linked through the discovered fields of references in the
  60      *   list.
  61      *   referent = null; discovered = next element in pending-Reference list.
  62      *
  63      *   Inactive: Neither Active nor Pending.
  64      *   referent = null.
  65      *
  66      *   Registered: Associated with a queue when created, and not yet added
  67      *   to the queue.
  68      *   queue = the associated queue.
  69      *
  70      *   Enqueued: Added to the associated queue, and not yet removed.
  71      *   queue = ReferenceQueue.ENQUEUE; next = next entry in list, or this to
  72      *   indicate end of list.
  73      *
  74      *   Dequeued: Added to the associated queue and then removed.
  75      *   queue = ReferenceQueue.NULL; next = this.
  76      *
  77      *   Unregistered: Not associated with a queue when created.
  78      *   queue = ReferenceQueue.NULL.
  79      *
  80      * The collector only needs to examine the referent field and the
  81      * discovered field to determine whether a (non-FinalReference) Reference
  82      * object needs special treatment.  If the referent is non-null and not
  83      * known to be live, then it may need to be discovered for possible later
  84      * notification.  But if the discovered field is non-null, then it has
  85      * already been discovered.
  86      *
  87      * FinalReference (which exists to support finalization) differs from
  88      * other references, because a FinalReference is not cleared when
  89      * notified.  The referent being null or not cannot be used to distinguish
  90      * between the active state and pending or inactive states.  However,
  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.
 149      */
 150 
 151     private T referent;         /* Treated specially by GC */
 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      */
 161     volatile ReferenceQueue<? super T> queue;
 162 
 163     /* The link in a ReferenceQueue's list of Reference objects.
 164      *
 165      * When registered: null
 166      *        enqueued: next element in queue (or this if last)
 167      *        dequeued: this (marking FinalReferences as inactive)
 168      *    unregistered: null


 199 
 200         static {
 201             // pre-load and initialize Cleaner class so that we don't
 202             // get into trouble later in the run loop if there's
 203             // memory shortage while loading/initializing it lazily.
 204             ensureClassInitialized(Cleaner.class);
 205         }
 206 
 207         ReferenceHandler(ThreadGroup g, String name) {
 208             super(g, null, name, 0, false);
 209         }
 210 
 211         public void run() {
 212             while (true) {
 213                 processPendingReferences();
 214             }
 215         }
 216     }
 217 
 218     /*
 219      * Atomically get and clear (set to null) the VM's pending-Reference list.
 220      */
 221     private static native Reference<Object> getAndClearReferencePendingList();
 222 
 223     /*
 224      * Test whether the VM's pending-Reference list contains any entries.
 225      */
 226     private static native boolean hasReferencePendingList();
 227 
 228     /*
 229      * Wait until the VM's pending-Reference list may be non-null.
 230      */
 231     private static native void waitForReferencePendingList();
 232 
 233     private static final Object processPendingLock = new Object();
 234     private static boolean processPendingActive = false;
 235 
 236     private static void processPendingReferences() {
 237         // Only the singleton reference processing thread calls
 238         // waitForReferencePendingList() and getAndClearReferencePendingList().
 239         // These are separate operations to avoid a race with other threads
 240         // that are calling waitForReferenceProcessing().
 241         waitForReferencePendingList();
 242         Reference<Object> pendingList;
 243         synchronized (processPendingLock) {
 244             pendingList = getAndClearReferencePendingList();
 245             processPendingActive = true;
 246         }
 247         while (pendingList != null) {
 248             Reference<Object> ref = pendingList;
 249             pendingList = ref.discovered;


< prev index next >