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

Print this page

        

*** 25,35 **** package java.lang.ref; import sun.misc.Cleaner; - /** * Abstract base class for reference objects. This class defines the * operations common to all reference objects. Because reference objects are * implemented in close cooperation with the garbage collector, this class may * not be subclassed directly. --- 25,34 ----
*** 67,77 **** * Active: queue = ReferenceQueue with which instance is registered, or * ReferenceQueue.NULL if it was not registered with a queue; next = * null. * * Pending: queue = ReferenceQueue with which instance is registered; ! * next = Following instance in queue, or this if at end of list. * * Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance * in queue, or this if at end of list. * * Inactive: queue = ReferenceQueue.NULL; next = this. --- 66,76 ---- * Active: queue = ReferenceQueue with which instance is registered, or * ReferenceQueue.NULL if it was not registered with a queue; next = * null. * * Pending: queue = ReferenceQueue with which instance is registered; ! * next = this * * Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance * in queue, or this if at end of list. * * Inactive: queue = ReferenceQueue.NULL; next = this.
*** 79,99 **** * With this scheme the collector need only examine the next field in order * to determine whether a Reference instance requires special treatment: If * the next field is null then the instance is active; if it is non-null, * then the collector should treat the instance normally. * ! * To ensure that concurrent collector can discover active Reference * objects without interfering with application threads that may apply * the enqueue() method to those objects, collectors should link ! * discovered objects through the discovered field. */ private T referent; /* Treated specially by GC */ ReferenceQueue<? super T> queue; Reference next; transient private Reference<T> discovered; /* used by VM */ /* Object used to synchronize with the garbage collector. The collector * must acquire this lock at the beginning of each collection cycle. It is --- 78,109 ---- * With this scheme the collector need only examine the next field in order * to determine whether a Reference instance requires special treatment: If * the next field is null then the instance is active; if it is non-null, * then the collector should treat the instance normally. * ! * To ensure that a concurrent collector can discover active Reference * objects without interfering with application threads that may apply * the enqueue() method to those objects, collectors should link ! * discovered objects through the discovered field. The discovered ! * field is also used for linking Reference objects in the pending list. */ private T referent; /* Treated specially by GC */ ReferenceQueue<? super T> queue; + /* When active: NULL + * pending: this + * Enqueued: next reference in queue (or this if last) + * Inactive: this + */ Reference next; + + /* When active: next element in a discovered reference list maintained by GC + * pending: next element in the pending list (or null if last) + * otherwise: NULL + */ transient private Reference<T> discovered; /* used by VM */ /* Object used to synchronize with the garbage collector. The collector * must acquire this lock at the beginning of each collection cycle. It is
*** 104,114 **** private static Lock lock = new Lock(); /* List of References waiting to be enqueued. The collector adds * References to this list, while the Reference-handler thread removes ! * them. This list is protected by the above lock object. */ private static Reference pending = null; /* High-priority thread to enqueue pending References */ --- 114,125 ---- private static Lock lock = new Lock(); /* List of References waiting to be enqueued. The collector adds * References to this list, while the Reference-handler thread removes ! * them. This list is protected by the above lock object. The ! * list uses the discovered field to link its elements. */ private static Reference pending = null; /* High-priority thread to enqueue pending References */
*** 118,135 **** super(g, name); } public void run() { for (;;) { - Reference r; synchronized (lock) { if (pending != null) { r = pending; ! Reference rn = r.next; ! pending = (rn == r) ? null : rn; ! r.next = r; } else { try { lock.wait(); } catch (InterruptedException x) { } continue; --- 129,144 ---- super(g, name); } public void run() { for (;;) { Reference r; synchronized (lock) { if (pending != null) { r = pending; ! pending = r.discovered; ! r.discovered = null; } else { try { lock.wait(); } catch (InterruptedException x) { } continue;
*** 199,212 **** * * @return <code>true</code> if and only if this reference object has * been enqueued */ public boolean isEnqueued() { - /* In terms of the internal states, this predicate actually tests - whether the instance is either Pending or Enqueued */ synchronized (this) { ! return (this.queue != ReferenceQueue.NULL) && (this.next != null); } } /** * Adds this reference object to the queue with which it is registered, --- 208,219 ---- * * @return <code>true</code> if and only if this reference object has * been enqueued */ public boolean isEnqueued() { synchronized (this) { ! return (this.next != null && this.queue == ReferenceQueue.ENQUEUED); } } /** * Adds this reference object to the queue with which it is registered,