Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/java/lang/ref/Reference.java
+++ new/src/share/classes/java/lang/ref/Reference.java
1 1 /*
2 2 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Oracle designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Oracle in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
20 20 *
21 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 22 * or visit www.oracle.com if you need additional information or have any
23 23 * questions.
24 24 */
25 25
26 26 package java.lang.ref;
27 27
28 28 import sun.misc.Cleaner;
29 29
30 -
31 30 /**
32 31 * Abstract base class for reference objects. This class defines the
33 32 * operations common to all reference objects. Because reference objects are
34 33 * implemented in close cooperation with the garbage collector, this class may
35 34 * not be subclassed directly.
36 35 *
37 36 * @author Mark Reinhold
38 37 * @since 1.2
39 38 */
40 39
41 40 public abstract class Reference<T> {
42 41
43 42 /* A Reference instance is in one of four possible internal states:
44 43 *
45 44 * Active: Subject to special treatment by the garbage collector. Some
46 45 * time after the collector detects that the reachability of the
47 46 * referent has changed to the appropriate state, it changes the
48 47 * instance's state to either Pending or Inactive, depending upon
49 48 * whether or not the instance was registered with a queue when it was
50 49 * created. In the former case it also adds the instance to the
51 50 * pending-Reference list. Newly-created instances are Active.
52 51 *
53 52 * Pending: An element of the pending-Reference list, waiting to be
54 53 * enqueued by the Reference-handler thread. Unregistered instances
55 54 * are never in this state.
56 55 *
57 56 * Enqueued: An element of the queue with which the instance was
58 57 * registered when it was created. When an instance is removed from
59 58 * its ReferenceQueue, it is made Inactive. Unregistered instances are
60 59 * never in this state.
61 60 *
↓ open down ↓ |
21 lines elided |
↑ open up ↑ |
62 61 * Inactive: Nothing more to do. Once an instance becomes Inactive its
63 62 * state will never change again.
64 63 *
65 64 * The state is encoded in the queue and next fields as follows:
66 65 *
67 66 * Active: queue = ReferenceQueue with which instance is registered, or
68 67 * ReferenceQueue.NULL if it was not registered with a queue; next =
69 68 * null.
70 69 *
71 70 * Pending: queue = ReferenceQueue with which instance is registered;
72 - * next = Following instance in queue, or this if at end of list.
71 + * next = this
73 72 *
74 73 * Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
75 74 * in queue, or this if at end of list.
76 75 *
77 76 * Inactive: queue = ReferenceQueue.NULL; next = this.
78 77 *
79 78 * With this scheme the collector need only examine the next field in order
80 79 * to determine whether a Reference instance requires special treatment: If
81 80 * the next field is null then the instance is active; if it is non-null,
82 81 * then the collector should treat the instance normally.
83 82 *
84 - * To ensure that concurrent collector can discover active Reference
83 + * To ensure that a concurrent collector can discover active Reference
85 84 * objects without interfering with application threads that may apply
86 85 * the enqueue() method to those objects, collectors should link
87 - * discovered objects through the discovered field.
86 + * discovered objects through the discovered field. The discovered
87 + * field is also used for linking Reference objects in the pending list.
88 88 */
89 89
90 90 private T referent; /* Treated specially by GC */
91 91
92 92 ReferenceQueue<? super T> queue;
93 -
93 +
94 + /* When active: NULL
95 + * pending: this
96 + * Enqueued: next reference in queue (or this if last)
97 + * Inactive: this
98 + */
94 99 Reference next;
100 +
101 + /* When active: next element in a discovered reference list maintained by GC
102 + * pending: next element in the pending list (or null if last)
103 + * otherwise: NULL
104 + */
95 105 transient private Reference<T> discovered; /* used by VM */
96 106
97 107
98 108 /* Object used to synchronize with the garbage collector. The collector
99 109 * must acquire this lock at the beginning of each collection cycle. It is
100 110 * therefore critical that any code holding this lock complete as quickly
101 111 * as possible, allocate no new objects, and avoid calling user code.
102 112 */
103 113 static private class Lock { };
104 114 private static Lock lock = new Lock();
105 115
106 116
107 117 /* List of References waiting to be enqueued. The collector adds
108 118 * References to this list, while the Reference-handler thread removes
109 - * them. This list is protected by the above lock object.
119 + * them. This list is protected by the above lock object. The
120 + * list uses the discovered field to link its elements.
110 121 */
111 122 private static Reference pending = null;
112 123
113 124 /* High-priority thread to enqueue pending References
114 125 */
115 126 private static class ReferenceHandler extends Thread {
116 127
117 128 ReferenceHandler(ThreadGroup g, String name) {
118 129 super(g, name);
119 130 }
120 131
121 132 public void run() {
122 133 for (;;) {
123 -
124 134 Reference r;
125 135 synchronized (lock) {
126 136 if (pending != null) {
127 137 r = pending;
128 - Reference rn = r.next;
129 - pending = (rn == r) ? null : rn;
130 - r.next = r;
138 + pending = r.discovered;
139 + r.discovered = null;
131 140 } else {
132 141 try {
133 142 lock.wait();
134 143 } catch (InterruptedException x) { }
135 144 continue;
136 145 }
137 146 }
138 147
139 148 // Fast path for cleaners
140 149 if (r instanceof Cleaner) {
141 150 ((Cleaner)r).clean();
142 151 continue;
143 152 }
144 153
145 154 ReferenceQueue q = r.queue;
146 155 if (q != ReferenceQueue.NULL) q.enqueue(r);
147 156 }
148 157 }
149 158 }
150 159
151 160 static {
152 161 ThreadGroup tg = Thread.currentThread().getThreadGroup();
153 162 for (ThreadGroup tgn = tg;
154 163 tgn != null;
155 164 tg = tgn, tgn = tg.getParent());
156 165 Thread handler = new ReferenceHandler(tg, "Reference Handler");
157 166 /* If there were a special system-only priority greater than
158 167 * MAX_PRIORITY, it would be used here
159 168 */
160 169 handler.setPriority(Thread.MAX_PRIORITY);
161 170 handler.setDaemon(true);
162 171 handler.start();
163 172 }
164 173
165 174
166 175 /* -- Referent accessor and setters -- */
167 176
168 177 /**
169 178 * Returns this reference object's referent. If this reference object has
170 179 * been cleared, either by the program or by the garbage collector, then
171 180 * this method returns <code>null</code>.
172 181 *
173 182 * @return The object to which this reference refers, or
174 183 * <code>null</code> if this reference object has been cleared
175 184 */
176 185 public T get() {
177 186 return this.referent;
178 187 }
179 188
180 189 /**
181 190 * Clears this reference object. Invoking this method will not cause this
182 191 * object to be enqueued.
183 192 *
184 193 * <p> This method is invoked only by Java code; when the garbage collector
185 194 * clears references it does so directly, without invoking this method.
186 195 */
187 196 public void clear() {
188 197 this.referent = null;
189 198 }
190 199
191 200
192 201 /* -- Queue operations -- */
193 202
↓ open down ↓ |
53 lines elided |
↑ open up ↑ |
194 203 /**
195 204 * Tells whether or not this reference object has been enqueued, either by
196 205 * the program or by the garbage collector. If this reference object was
197 206 * not registered with a queue when it was created, then this method will
198 207 * always return <code>false</code>.
199 208 *
200 209 * @return <code>true</code> if and only if this reference object has
201 210 * been enqueued
202 211 */
203 212 public boolean isEnqueued() {
204 - /* In terms of the internal states, this predicate actually tests
205 - whether the instance is either Pending or Enqueued */
206 213 synchronized (this) {
207 - return (this.queue != ReferenceQueue.NULL) && (this.next != null);
214 + return (this.next != null && this.queue == ReferenceQueue.ENQUEUED);
208 215 }
209 216 }
210 217
211 218 /**
212 219 * Adds this reference object to the queue with which it is registered,
213 220 * if any.
214 221 *
215 222 * <p> This method is invoked only by Java code; when the garbage collector
216 223 * enqueues references it does so directly, without invoking this method.
217 224 *
218 225 * @return <code>true</code> if this reference object was successfully
219 226 * enqueued; <code>false</code> if it was already enqueued or if
220 227 * it was not registered with a queue when it was created
221 228 */
222 229 public boolean enqueue() {
223 230 return this.queue.enqueue(this);
224 231 }
225 232
226 233
227 234 /* -- Constructors -- */
228 235
229 236 Reference(T referent) {
230 237 this(referent, null);
231 238 }
232 239
233 240 Reference(T referent, ReferenceQueue<? super T> queue) {
234 241 this.referent = referent;
235 242 this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
236 243 }
237 244
238 245 }
↓ open down ↓ |
21 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX