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 ReferenceHandler(ThreadGroup g, String name) { 130 super(g, name); 131 } 132 133 public void run() { 134 for (;;) { 135 Reference<Object> r; 136 synchronized (lock) { 137 if (pending != null) { 138 r = pending; 139 pending = r.discovered; 140 r.discovered = null; 141 } else { 142 // The waiting on the lock may cause an OOME because it may try to allocate 143 // exception objects, so also catch OOME here to avoid silent exit of the 144 // reference handler thread. 145 // 146 // Explicitly define the order of the two exceptions we catch here 147 // when waiting for the lock. 148 // 149 // We do not want to try to potentially load the InterruptedException class 150 // (which would be done if this was its first use, and InterruptedException 151 // were checked first) in this situation. 152 // 153 // This may lead to the VM not ever trying to load the InterruptedException 154 // class again. 155 try { 156 try { 157 lock.wait(); 158 } catch (OutOfMemoryError x) { } 159 } catch (InterruptedException x) { } 160 continue; 161 } 162 } 163 164 // Fast path for cleaners 165 if (r instanceof Cleaner) { 166 ((Cleaner)r).clean(); 167 continue; 168 } 169 170 ReferenceQueue<Object> q = r.queue; 171 if (q != ReferenceQueue.NULL) q.enqueue(r); 172 } 173 } 174 } 175 176 static { 177 ThreadGroup tg = Thread.currentThread().getThreadGroup(); 178 for (ThreadGroup tgn = tg; 179 tgn != null; 180 tg = tgn, tgn = tg.getParent()); 181 Thread handler = new ReferenceHandler(tg, "Reference Handler"); 182 /* If there were a special system-only priority greater than 183 * MAX_PRIORITY, it would be used here 184 */ 185 handler.setPriority(Thread.MAX_PRIORITY); 186 handler.setDaemon(true); 187 handler.start(); 188 } 189 190 191 /* -- Referent accessor and setters -- */ 192 193 /** 194 * Returns this reference object's referent. If this reference object has 195 * been cleared, either by the program or by the garbage collector, then 196 * this method returns <code>null</code>. 197 * 198 * @return The object to which this reference refers, or 199 * <code>null</code> if this reference object has been cleared 200 */ 201 public T get() { 202 return this.referent; 203 } 204 205 /** 206 * Clears this reference object. Invoking this method will not cause this 207 * object to be enqueued. 208 * 209 * <p> This method is invoked only by Java code; when the garbage collector 210 * clears references it does so directly, without invoking this method. 211 */ 212 public void clear() { 213 this.referent = null; 214 } 215 216 217 /* -- Queue operations -- */ 218 219 /** 220 * Tells whether or not this reference object has been enqueued, either by 221 * the program or by the garbage collector. If this reference object was 222 * not registered with a queue when it was created, then this method will 223 * always return <code>false</code>. 224 * 225 * @return <code>true</code> if and only if this reference object has 226 * been enqueued 227 */ 228 public boolean isEnqueued() { 229 return (this.queue == ReferenceQueue.ENQUEUED); 230 } 231 232 /** 233 * Adds this reference object to the queue with which it is registered, 234 * if any. 235 * 236 * <p> This method is invoked only by Java code; when the garbage collector 237 * enqueues references it does so directly, without invoking this method. 238 * 239 * @return <code>true</code> if this reference object was successfully 240 * enqueued; <code>false</code> if it was already enqueued or if 241 * it was not registered with a queue when it was created 242 */ 243 public boolean enqueue() { 244 return this.queue.enqueue(this); 245 } 246 247 248 /* -- Constructors -- */ 249 250 Reference(T referent) { 251 this(referent, null); 252 } 253 254 Reference(T referent, ReferenceQueue<? super T> queue) { 255 this.referent = referent; 256 this.queue = (queue == null) ? ReferenceQueue.NULL : queue; 257 } 258 259 }