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