Print this page


Split Close
Expand all
Collapse all
          --- old/src/share/classes/java/lang/ref/Reference.java
          +++ new/src/share/classes/java/lang/ref/Reference.java
↓ open down ↓ 19 lines elided ↑ open up ↑
  20   20   *
  21   21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22   22   * or visit www.oracle.com if you need additional information or have any
  23   23   * questions.
  24   24   */
  25   25  
  26   26  package java.lang.ref;
  27   27  
  28   28  import sun.misc.Cleaner;
  29   29  
  30      -
  31   30  /**
  32   31   * Abstract base class for reference objects.  This class defines the
  33   32   * operations common to all reference objects.  Because reference objects are
  34   33   * implemented in close cooperation with the garbage collector, this class may
  35   34   * not be subclassed directly.
  36   35   *
  37   36   * @author   Mark Reinhold
  38   37   * @since    1.2
  39   38   */
  40   39  
↓ open down ↓ 21 lines elided ↑ open up ↑
  62   61       *     Inactive: Nothing more to do.  Once an instance becomes Inactive its
  63   62       *     state will never change again.
  64   63       *
  65   64       * The state is encoded in the queue and next fields as follows:
  66   65       *
  67   66       *     Active: queue = ReferenceQueue with which instance is registered, or
  68   67       *     ReferenceQueue.NULL if it was not registered with a queue; next =
  69   68       *     null.
  70   69       *
  71   70       *     Pending: queue = ReferenceQueue with which instance is registered;
  72      -     *     next = Following instance in queue, or this if at end of list.
       71 +     *     next = this
  73   72       *
  74   73       *     Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
  75   74       *     in queue, or this if at end of list.
  76   75       *
  77   76       *     Inactive: queue = ReferenceQueue.NULL; next = this.
  78   77       *
  79   78       * With this scheme the collector need only examine the next field in order
  80   79       * to determine whether a Reference instance requires special treatment: If
  81   80       * the next field is null then the instance is active; if it is non-null,
  82   81       * then the collector should treat the instance normally.
  83   82       *
  84      -     * To ensure that concurrent collector can discover active Reference
       83 +     * To ensure that a concurrent collector can discover active Reference
  85   84       * objects without interfering with application threads that may apply
  86   85       * the enqueue() method to those objects, collectors should link
  87      -     * discovered objects through the discovered field.
       86 +     * discovered objects through the discovered field. The discovered
       87 +     * field is also used for linking Reference objects in the pending list.
  88   88       */
  89   89  
  90   90      private T referent;         /* Treated specially by GC */
  91   91  
  92   92      ReferenceQueue<? super T> queue;
  93      -
       93 +    
       94 +    /* When active:   NULL
       95 +     *     pending:   this
       96 +     *    Enqueued:   next reference in queue (or this if last)
       97 +     *    Inactive:   this
       98 +     */
  94   99      Reference next;
      100 +
      101 +    /* When active:   next element in a discovered reference list maintained by GC
      102 +     *     pending:   next element in the pending list (or null if last)
      103 +     *   otherwise:   NULL
      104 +     */
  95  105      transient private Reference<T> discovered;  /* used by VM */
  96  106  
  97  107  
  98  108      /* Object used to synchronize with the garbage collector.  The collector
  99  109       * must acquire this lock at the beginning of each collection cycle.  It is
 100  110       * therefore critical that any code holding this lock complete as quickly
 101  111       * as possible, allocate no new objects, and avoid calling user code.
 102  112       */
 103  113      static private class Lock { };
 104  114      private static Lock lock = new Lock();
 105  115  
 106  116  
 107  117      /* List of References waiting to be enqueued.  The collector adds
 108  118       * References to this list, while the Reference-handler thread removes
 109      -     * them.  This list is protected by the above lock object.
      119 +     * them.  This list is protected by the above lock object. The 
      120 +     * list uses the discovered field to link its elements. 
 110  121       */
 111  122      private static Reference pending = null;
 112  123  
 113  124      /* High-priority thread to enqueue pending References
 114  125       */
 115  126      private static class ReferenceHandler extends Thread {
 116  127  
 117  128          ReferenceHandler(ThreadGroup g, String name) {
 118  129              super(g, name);
 119  130          }
 120  131  
 121  132          public void run() {
 122  133              for (;;) {
 123      -
 124  134                  Reference r;
 125  135                  synchronized (lock) {
 126  136                      if (pending != null) {
 127  137                          r = pending;
 128      -                        Reference rn = r.next;
 129      -                        pending = (rn == r) ? null : rn;
 130      -                        r.next = r;
      138 +                        pending = r.discovered;
      139 +                        r.discovered = null;
 131  140                      } else {
 132  141                          try {
 133  142                              lock.wait();
 134  143                          } catch (InterruptedException x) { }
 135  144                          continue;
 136  145                      }
 137  146                  }
 138  147  
 139  148                  // Fast path for cleaners
 140  149                  if (r instanceof Cleaner) {
↓ open down ↓ 53 lines elided ↑ open up ↑
 194  203      /**
 195  204       * Tells whether or not this reference object has been enqueued, either by
 196  205       * the program or by the garbage collector.  If this reference object was
 197  206       * not registered with a queue when it was created, then this method will
 198  207       * always return <code>false</code>.
 199  208       *
 200  209       * @return   <code>true</code> if and only if this reference object has
 201  210       *           been enqueued
 202  211       */
 203  212      public boolean isEnqueued() {
 204      -        /* In terms of the internal states, this predicate actually tests
 205      -           whether the instance is either Pending or Enqueued */
 206  213          synchronized (this) {
 207      -            return (this.queue != ReferenceQueue.NULL) && (this.next != null);
      214 +            return (this.next != null && this.queue == ReferenceQueue.ENQUEUED); 
 208  215          }
 209  216      }
 210  217  
 211  218      /**
 212  219       * Adds this reference object to the queue with which it is registered,
 213  220       * if any.
 214  221       *
 215  222       * <p> This method is invoked only by Java code; when the garbage collector
 216  223       * enqueues references it does so directly, without invoking this method.
 217  224       *
↓ open down ↓ 21 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX