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 (non-FinalReference)
80 * Reference object needs special treatment. If the referent is non-null
81 * and not known to be live, then it may need to be discovered for
82 * possible later notification. But if the discovered field is non-null,
83 * then either (1) it has already been discovered, or (2) it is in the
84 * pending list.
85 *
86 * FinalReference (which exists to support finalization, which was
87 * deprecated in JDK 9) differs from normal references, because a
88 * FinalReference is not cleared when notified. The referent being null
89 * or not cannot be used to distinguish between the active state and
90 * pending or inactive states. However, FinalReferences do not support
91 * enqueue(). Instead, the next field of a FinalReference object is set
92 * to "this" when it is added to the pending list. The use of "this"
93 * as the value of next in the enqueued and dequeued states maintains the
94 * non-active state. An additional check that the next field is null is
95 * required to determine that a FinalReference object is active.
96 *
97 * Initial states:
98 * active/registered
99 * active/unregistered [1]
100 *
101 * Transitions:
102 * active/registered -> pending/registered - GC
103 * -> inactive/registered - clear
104 * -> inactive/enqueued - enqueue [2]
105 * pending/registered -> pending/enqueued - enqueue [2]
106 * -> inactive/enqueued - pending list processing
107 * pending/enqueued -> inactive/enqueued - pending list processing
108 * -> pending/dequeued - poll/remove
109 * pending/dequeued -> inactive/dequeued - pending list processing
110 * inactive/registered -> inactive/enqueued - enqueue [2]
111 * inactive/enqueued -> inactive/dequeued - poll/remove
112 *
113 * active/unregistered -> pending/unregistered - GC
114 * -> inactive/unregistered - GC, clear, enqueue
115 * pending/unregistered -> inactive/unregistered - pending list processing
116 *
117 * Terminal states:
118 * inactive/dequeued
119 * inactive/unregistered
120 *
121 * Unreachable states (because enqueue also clears):
122 * active/enqeued
123 * active/dequeued
124 *
125 * [1] Unregistered is not permitted for FinalReferences.
126 *
127 * [2] These transitions are not possible for FinalReferences, making
128 * pending/enqueued and pending/dequeued unreachable, and
129 * inactive/registered terminal.
130 */
131
132 private T referent; /* Treated specially by GC */
133
134 /* The queue this reference gets enqueued to by GC notification or by
135 * calling enqueue().
136 *
137 * When registered: the queue with which this reference is registered.
138 * enqueued: ReferenceQueue.ENQUEUE
139 * dequeued: ReferenceQueue.NULL
140 * unregistered: ReferenceQueue.NULL
141 */
142 volatile ReferenceQueue<? super T> queue;
143
144 /* The link in a ReferenceQueue's list of Reference objects.
145 *
146 * When registered: null
147 * enqueued: next element in queue (or this if last)
148 * dequeued: this (marking FinalReferences as inactive)
149 * unregistered: null
180
181 static {
182 // pre-load and initialize Cleaner class so that we don't
183 // get into trouble later in the run loop if there's
184 // memory shortage while loading/initializing it lazily.
185 ensureClassInitialized(Cleaner.class);
186 }
187
188 ReferenceHandler(ThreadGroup g, String name) {
189 super(g, null, name, 0, false);
190 }
191
192 public void run() {
193 while (true) {
194 processPendingReferences();
195 }
196 }
197 }
198
199 /*
200 * Atomically get and clear (set to null) the VM's pending list.
201 */
202 private static native Reference<Object> getAndClearReferencePendingList();
203
204 /*
205 * Test whether the VM's pending list contains any entries.
206 */
207 private static native boolean hasReferencePendingList();
208
209 /*
210 * Wait until the VM's pending list may be non-null.
211 */
212 private static native void waitForReferencePendingList();
213
214 private static final Object processPendingLock = new Object();
215 private static boolean processPendingActive = false;
216
217 private static void processPendingReferences() {
218 // Only the singleton reference processing thread calls
219 // waitForReferencePendingList() and getAndClearReferencePendingList().
220 // These are separate operations to avoid a race with other threads
221 // that are calling waitForReferenceProcessing().
222 waitForReferencePendingList();
223 Reference<Object> pendingList;
224 synchronized (processPendingLock) {
225 pendingList = getAndClearReferencePendingList();
226 processPendingActive = true;
227 }
228 while (pendingList != null) {
229 Reference<Object> ref = pendingList;
230 pendingList = ref.discovered;
|
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
52 * referent has changed to the appropriate state, the collector
53 * "notifies" the reference, changing the state to either "pending" or
54 * "inactive".
55 * referent != null; discovered = null, or in GC discovered list.
56 *
57 * Pending: An element of the pending-Reference list, waiting to be
58 * processed by the ReferenceHandler thread. The pending-Reference
59 * list is linked through the discovered fields of references in the
60 * list.
61 * referent = null; discovered = next element in pending-Reference list.
62 *
63 * Inactive: Neither Active nor Pending.
64 * referent = null.
65 *
66 * Registered: Associated with a queue when created, and not yet added
67 * to the queue.
68 * queue = the associated queue.
69 *
70 * Enqueued: Added to the associated queue, and not yet removed.
71 * queue = ReferenceQueue.ENQUEUE; next = next entry in list, or this to
72 * indicate end of list.
73 *
74 * Dequeued: Added to the associated queue and then removed.
75 * queue = ReferenceQueue.NULL; next = this.
76 *
77 * Unregistered: Not associated with a queue when created.
78 * queue = ReferenceQueue.NULL.
79 *
80 * The collector only needs to examine the referent field and the
81 * discovered field to determine whether a (non-FinalReference) Reference
82 * object needs special treatment. If the referent is non-null and not
83 * known to be live, then it may need to be discovered for possible later
84 * notification. But if the discovered field is non-null, then it has
85 * already been discovered.
86 *
87 * FinalReference (which exists to support finalization) differs from
88 * other references, because a FinalReference is not cleared when
89 * notified. The referent being null or not cannot be used to distinguish
90 * between the active state and pending or inactive states. However,
91 * FinalReferences do not support enqueue(). Instead, the next field of a
92 * FinalReference object is set to "this" when it is added to the
93 * pending-Reference list. The use of "this" as the value of next in the
94 * enqueued and dequeued states maintains the non-active state. An
95 * additional check that the next field is null is required to determine
96 * that a FinalReference object is active.
97 *
98 * Initial states:
99 * [active/registered]
100 * [active/unregistered] [1]
101 *
102 * Transitions:
103 * clear
104 * [active/registered] -------> [inactive/registered]
105 * | |
106 * | | enqueue [2]
107 * | GC enqueue [2] |
108 * | -----------------|
109 * | |
110 * v |
111 * [pending/registered] --- v
112 * | | ReferenceHandler
113 * | enqueue [2] |---> [inactive/enqueued]
114 * v | |
115 * [pending/enqueued] --- |
116 * | | poll/remove
117 * | poll/remove |
118 * | |
119 * v ReferenceHandler v
120 * [pending/dequeued] ------> [inactive/dequeued]
121 *
122 *
123 * clear/enqueue/GC [3]
124 * [active/unregistered] ------
125 * | |
126 * | GC |
127 * | |--> [inactive/unregistered]
128 * v |
129 * [pending/unregistered] ------
130 * ReferenceHandler
131 *
132 * Terminal states:
133 * [inactive/dequeued]
134 * [inactive/unregistered]
135 *
136 * Unreachable states (because enqueue also clears):
137 * [active/enqeued]
138 * [active/dequeued]
139 *
140 * [1] Unregistered is not permitted for FinalReferences.
141 *
142 * [2] These transitions are not possible for FinalReferences, making
143 * [pending/enqueued] and [pending/dequeued] unreachable, and
144 * [inactive/registered] terminal.
145 *
146 * [3] The garbage collector may directly transition a Reference
147 * from [active/unregistered] to [inactive/unregistered],
148 * bypassing the pending-Reference list.
149 */
150
151 private T referent; /* Treated specially by GC */
152
153 /* The queue this reference gets enqueued to by GC notification or by
154 * calling enqueue().
155 *
156 * When registered: the queue with which this reference is registered.
157 * enqueued: ReferenceQueue.ENQUEUE
158 * dequeued: ReferenceQueue.NULL
159 * unregistered: ReferenceQueue.NULL
160 */
161 volatile ReferenceQueue<? super T> queue;
162
163 /* The link in a ReferenceQueue's list of Reference objects.
164 *
165 * When registered: null
166 * enqueued: next element in queue (or this if last)
167 * dequeued: this (marking FinalReferences as inactive)
168 * unregistered: null
199
200 static {
201 // pre-load and initialize Cleaner class so that we don't
202 // get into trouble later in the run loop if there's
203 // memory shortage while loading/initializing it lazily.
204 ensureClassInitialized(Cleaner.class);
205 }
206
207 ReferenceHandler(ThreadGroup g, String name) {
208 super(g, null, name, 0, false);
209 }
210
211 public void run() {
212 while (true) {
213 processPendingReferences();
214 }
215 }
216 }
217
218 /*
219 * Atomically get and clear (set to null) the VM's pending-Reference list.
220 */
221 private static native Reference<Object> getAndClearReferencePendingList();
222
223 /*
224 * Test whether the VM's pending-Reference list contains any entries.
225 */
226 private static native boolean hasReferencePendingList();
227
228 /*
229 * Wait until the VM's pending-Reference list may be non-null.
230 */
231 private static native void waitForReferencePendingList();
232
233 private static final Object processPendingLock = new Object();
234 private static boolean processPendingActive = false;
235
236 private static void processPendingReferences() {
237 // Only the singleton reference processing thread calls
238 // waitForReferencePendingList() and getAndClearReferencePendingList().
239 // These are separate operations to avoid a race with other threads
240 // that are calling waitForReferenceProcessing().
241 waitForReferencePendingList();
242 Reference<Object> pendingList;
243 synchronized (processPendingLock) {
244 pendingList = getAndClearReferencePendingList();
245 processPendingActive = true;
246 }
247 while (pendingList != null) {
248 Reference<Object> ref = pendingList;
249 pendingList = ref.discovered;
|