< 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 >