26 package java.lang.ref;
27
28 import jdk.internal.vm.annotation.ForceInline;
29 import jdk.internal.HotSpotIntrinsicCandidate;
30 import jdk.internal.misc.JavaLangRefAccess;
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 /* A Reference instance is in one of four possible internal states:
47 *
48 * Active: Subject to special treatment by the garbage collector. Some
49 * time after the collector detects that the reachability of the
50 * referent has changed to the appropriate state, it changes the
51 * instance's state to either Pending or Inactive, depending upon
52 * whether or not the instance was registered with a queue when it was
53 * created. In the former case it also adds the instance to the
54 * pending-Reference list. Newly-created instances are Active.
55 *
56 * Pending: An element of the pending-Reference list, waiting to be
57 * enqueued by the Reference-handler thread. Unregistered instances
58 * are never in this state.
59 *
60 * Enqueued: An element of the queue with which the instance was
61 * registered when it was created. When an instance is removed from
62 * its ReferenceQueue, it is made Inactive. Unregistered instances are
63 * never in this state.
64 *
65 * Inactive: Nothing more to do. Once an instance becomes Inactive its
66 * state will never change again.
67 *
68 * The state is encoded in the queue and next fields as follows:
69 *
70 * Active: queue = ReferenceQueue with which instance is registered, or
71 * ReferenceQueue.NULL if it was not registered with a queue; next =
72 * null.
73 *
74 * Pending: queue = ReferenceQueue with which instance is registered;
75 * next = this
76 *
77 * Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
78 * in queue, or this if at end of list.
79 *
80 * Inactive: queue = ReferenceQueue.NULL; next = this.
81 *
82 * With this scheme the collector need only examine the next field in order
83 * to determine whether a Reference instance requires special treatment: If
84 * the next field is null then the instance is active; if it is non-null,
85 * then the collector should treat the instance normally.
86 *
87 * To ensure that a concurrent collector can discover active Reference
88 * objects without interfering with application threads that may apply
89 * the enqueue() method to those objects, collectors should link
90 * discovered objects through the discovered field. The discovered
91 * field is also used for linking Reference objects in the pending list.
92 */
93
94 private T referent; /* Treated specially by GC */
95
96 volatile ReferenceQueue<? super T> queue;
97
98 /* When active: NULL
99 * pending: this
100 * Enqueued: next reference in queue (or this if last)
101 * Inactive: this
102 */
103 @SuppressWarnings("rawtypes")
104 volatile Reference next;
105
106 /* When active: next element in a discovered reference list maintained by GC (or this if last)
107 * pending: next element in the pending list (or null if last)
108 * otherwise: NULL
109 */
110 private transient Reference<T> discovered; /* used by VM */
111
112
113 /* High-priority thread to enqueue pending References
114 */
115 private static class ReferenceHandler extends Thread {
116
117 private static void ensureClassInitialized(Class<?> clazz) {
118 try {
119 Class.forName(clazz.getName(), true, clazz.getClassLoader());
120 } catch (ClassNotFoundException e) {
121 throw (Error) new NoClassDefFoundError(e.getMessage()).initCause(e);
122 }
123 }
124
125 static {
126 // pre-load and initialize Cleaner class so that we don't
127 // get into trouble later in the run loop if there's
128 // memory shortage while loading/initializing it lazily.
129 ensureClassInitialized(Cleaner.class);
130 }
|
26 package java.lang.ref;
27
28 import jdk.internal.vm.annotation.ForceInline;
29 import jdk.internal.HotSpotIntrinsicCandidate;
30 import jdk.internal.misc.JavaLangRefAccess;
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 Reference object needs
80 * special treatment. If the referent is non-null and not known to be
81 * live, then it may need to be discovered for possible later
82 * notification. But if the discovered field is non-null, then either (1)
83 * it has already been discovered, or (2) it is in the pending list.
84 *
85 * FinalReference differs from other references, because a FinalReference
86 * is not cleared when notified. The referent being null or not cannot be
87 * used to distinguish between the active state and pending or inactive
88 * states. However, FinalReferences do not support enqueue(). Instead,
89 * the next field of a FinalReference object is set to the object when it
90 * is added to the pending list, and the use of this as the value of next
91 * in the enqueued and dequeued states maintains the non-active state. An
92 * additional check that the next field is null is required to determine
93 * that a FinalReference object is active.
94 *
95 * Initial states:
96 * active/registered
97 * active/unregistered [1]
98 *
99 * Transitions:
100 * active/registered -> pending/registered - GC
101 * -> inactive/registered - clear
102 * -> inactive/enqueued - enqueue [2]
103 * pending/registered -> pending/enqueued - enqueue [2]
104 * -> inactive/enqueued - pending list processing
105 * pending/enqueued -> inactive/enqueued - pending list processing
106 * -> pending/dequeued - poll/remove
107 * pending/dequeued -> inactive/dequeued - pending list processing
108 * inactive/registered -> inactive/enqueued - enqueue [2]
109 * inactive/enqueued -> inactive/dequeued - poll/remove
110 *
111 * active/unregistered -> pending/unregistered - GC
112 * -> inactive/unregistered - GC, clear, enqueue
113 * pending/unregistered -> inactive/unregistered - pending list processing
114 *
115 * Terminal states:
116 * inactive/dequeued
117 * inactive/unregistered
118 *
119 * Unreachable states (because enqueue also clears):
120 * active/enqeued
121 * active/dequeued
122 *
123 * [1] Unregistered is not permitted for FinalReferences.
124 *
125 * [2] These transitions are not possible for FinalReferences, making
126 * pending/enqueued and pending/dequeued unreachable, and
127 * inactive/registered terminal.
128 */
129
130 private T referent; /* Treated specially by GC */
131
132 volatile ReferenceQueue<? super T> queue;
133
134 /* The link in a ReferenceQueue's list of Reference objects.
135 *
136 * When registered: null
137 * enqueued: next element in queue (or this if last)
138 * dequeued: this (marking FinalReferences as inactive)
139 * unregistered: null
140 */
141 @SuppressWarnings("rawtypes")
142 volatile Reference next;
143
144 /* Used by the garbage collector to accumulate Reference objects that need
145 * to be revisited in order to decide whether they should be notified.
146 * Also used as the link in the pending-Reference list. The discovered
147 * field and the next field are distinct to allow the enqueue() method to
148 * be applied to a Reference object while it is either in the
149 * pending-Reference list or in the garbage collector's discovered set.
150 *
151 * When active: null or next element in a discovered reference list
152 * maintained by the GC (or this if last)
153 * pending: next element in the pending-Reference list (null if last)
154 * inactive: null
155 */
156 private transient Reference<T> discovered;
157
158
159 /* High-priority thread to enqueue pending References
160 */
161 private static class ReferenceHandler extends Thread {
162
163 private static void ensureClassInitialized(Class<?> clazz) {
164 try {
165 Class.forName(clazz.getName(), true, clazz.getClassLoader());
166 } catch (ClassNotFoundException e) {
167 throw (Error) new NoClassDefFoundError(e.getMessage()).initCause(e);
168 }
169 }
170
171 static {
172 // pre-load and initialize Cleaner class so that we don't
173 // get into trouble later in the run loop if there's
174 // memory shortage while loading/initializing it lazily.
175 ensureClassInitialized(Cleaner.class);
176 }
|