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