< prev index next >

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

Print this page
rev 50107 : [mq]: pp2_work
rev 50108 : [mq]: tschatzl_1
rev 50109 : [mq]: mr_comments
rev 50110 : [mq]: mandy_1

*** 41,115 **** * @since 1.2 */ public abstract class Reference<T> { ! /* 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. * * Pending: An element of the pending-Reference list, waiting to be ! * enqueued by the Reference-handler thread. Unregistered instances ! * are never in this state. ! * ! * Enqueued: An element of the queue with which the instance was ! * registered when it was created. When an instance is removed from ! * its ReferenceQueue, it is made Inactive. Unregistered instances are ! * never in this state. ! * ! * Inactive: Nothing more to do. Once an instance becomes Inactive its ! * state will never change again. ! * ! * The state is encoded in the queue and next fields as follows: ! * ! * 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. ! * ! * 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 */ volatile ReferenceQueue<? super T> queue; ! /* When active: NULL ! * pending: this ! * Enqueued: next reference in queue (or this if last) ! * Inactive: this */ @SuppressWarnings("rawtypes") volatile Reference next; ! /* When active: next element in a discovered reference list maintained by GC (or this if last) ! * pending: next element in the pending list (or null if last) ! * otherwise: NULL */ ! private transient Reference<T> discovered; /* used by VM */ /* High-priority thread to enqueue pending References */ private static class ReferenceHandler extends Thread { --- 41,190 ---- * @since 1.2 */ public abstract class Reference<T> { ! /* The state of a Reference object is characterized by two attributes. It ! * may be either "active", "pending", or "inactive". It may also be ! * either "registered", "enqueued", "dequeued", or "unregistered". * * 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, the collector ! * "notifies" the reference, changing the state to either "pending" or ! * "inactive". ! * referent != null; discovered = null, or in GC discovered list. * * Pending: An element of the pending-Reference list, waiting to be ! * processed by the ReferenceHandler thread. The pending-Reference ! * list is linked through the discovered fields of references in the ! * list. ! * referent = null; discovered = next element in pending-Reference list. ! * ! * Inactive: Neither Active nor Pending. ! * referent = null. ! * ! * Registered: Associated with a queue when created, and not yet added ! * to the queue. ! * queue = the associated queue. ! * ! * Enqueued: Added to the associated queue, and not yet removed. ! * queue = ReferenceQueue.ENQUEUE; next = next entry in list, or this to ! * indicate end of list. ! * ! * Dequeued: Added to the associated queue and then removed. ! * queue = ReferenceQueue.NULL; next = this. ! * ! * Unregistered: Not associated with a queue when created. ! * queue = ReferenceQueue.NULL. ! * ! * The collector only needs to examine the referent field and the ! * discovered field to determine whether a (non-FinalReference) Reference ! * object needs special treatment. If the referent is non-null and not ! * known to be live, then it may need to be discovered for possible later ! * notification. But if the discovered field is non-null, then it has ! * already been discovered. ! * ! * FinalReference (which exists to support finalization) differs from ! * other references, because a FinalReference is not cleared when ! * notified. The referent being null or not cannot be used to distinguish ! * between the active state and pending or inactive states. However, ! * FinalReferences do not support enqueue(). Instead, the next field of a ! * FinalReference object is set to "this" when it is added to the ! * pending-Reference list. The use of "this" as the value of next in the ! * enqueued and dequeued states maintains the non-active state. An ! * additional check that the next field is null is required to determine ! * that a FinalReference object is active. ! * ! * Initial states: ! * [active/registered] ! * [active/unregistered] [1] ! * ! * Transitions: ! * clear ! * [active/registered] -------> [inactive/registered] ! * | | ! * | | enqueue [2] ! * | GC enqueue [2] | ! * | -----------------| ! * | | ! * v | ! * [pending/registered] --- v ! * | | ReferenceHandler ! * | enqueue [2] |---> [inactive/enqueued] ! * v | | ! * [pending/enqueued] --- | ! * | | poll/remove ! * | poll/remove | ! * | | ! * v ReferenceHandler v ! * [pending/dequeued] ------> [inactive/dequeued] ! * ! * ! * clear/enqueue/GC [3] ! * [active/unregistered] ------ ! * | | ! * | GC | ! * | |--> [inactive/unregistered] ! * v | ! * [pending/unregistered] ------ ! * ReferenceHandler ! * ! * Terminal states: ! * [inactive/dequeued] ! * [inactive/unregistered] ! * ! * Unreachable states (because enqueue also clears): ! * [active/enqeued] ! * [active/dequeued] ! * ! * [1] Unregistered is not permitted for FinalReferences. ! * ! * [2] These transitions are not possible for FinalReferences, making ! * [pending/enqueued] and [pending/dequeued] unreachable, and ! * [inactive/registered] terminal. ! * ! * [3] The garbage collector may directly transition a Reference ! * from [active/unregistered] to [inactive/unregistered], ! * bypassing the pending-Reference list. */ private T referent; /* Treated specially by GC */ + /* The queue this reference gets enqueued to by GC notification or by + * calling enqueue(). + * + * When registered: the queue with which this reference is registered. + * enqueued: ReferenceQueue.ENQUEUE + * dequeued: ReferenceQueue.NULL + * unregistered: ReferenceQueue.NULL + */ volatile ReferenceQueue<? super T> queue; ! /* The link in a ReferenceQueue's list of Reference objects. ! * ! * When registered: null ! * enqueued: next element in queue (or this if last) ! * dequeued: this (marking FinalReferences as inactive) ! * unregistered: null */ @SuppressWarnings("rawtypes") volatile Reference next; ! /* Used by the garbage collector to accumulate Reference objects that need ! * to be revisited in order to decide whether they should be notified. ! * Also used as the link in the pending-Reference list. The discovered ! * field and the next field are distinct to allow the enqueue() method to ! * be applied to a Reference object while it is either in the ! * pending-Reference list or in the garbage collector's discovered set. ! * ! * When active: null or next element in a discovered reference list ! * maintained by the GC (or this if last) ! * pending: next element in the pending-Reference list (null if last) ! * inactive: null */ ! private transient Reference<T> discovered; /* High-priority thread to enqueue pending References */ private static class ReferenceHandler extends Thread {
*** 139,159 **** } } } /* ! * Atomically get and clear (set to null) the VM's pending list. */ private static native Reference<Object> getAndClearReferencePendingList(); /* ! * Test whether the VM's pending list contains any entries. */ private static native boolean hasReferencePendingList(); /* ! * Wait until the VM's pending list may be non-null. */ private static native void waitForReferencePendingList(); private static final Object processPendingLock = new Object(); private static boolean processPendingActive = false; --- 214,234 ---- } } } /* ! * Atomically get and clear (set to null) the VM's pending-Reference list. */ private static native Reference<Object> getAndClearReferencePendingList(); /* ! * Test whether the VM's pending-Reference list contains any entries. */ private static native boolean hasReferencePendingList(); /* ! * Wait until the VM's pending-Reference list may be non-null. */ private static native void waitForReferencePendingList(); private static final Object processPendingLock = new Object(); private static boolean processPendingActive = false;
< prev index next >