< prev index next >

src/java.base/share/classes/java/lang/ref/Reference.java

Print this page

  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 jdk.internal.vm.annotation.ForceInline;
 29 import jdk.internal.vm.annotation.IntrinsicCandidate;
 30 import jdk.internal.access.JavaLangRefAccess;
 31 import jdk.internal.access.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

174 
175     /* Used by the garbage collector to accumulate Reference objects that need
176      * to be revisited in order to decide whether they should be notified.
177      * Also used as the link in the pending-Reference list.  The discovered
178      * field and the next field are distinct to allow the enqueue() method to
179      * be applied to a Reference object while it is either in the
180      * pending-Reference list or in the garbage collector's discovered set.
181      *
182      * When active: null or next element in a discovered reference list
183      *              maintained by the GC (or this if last)
184      *     pending: next element in the pending-Reference list (null if last)
185      *    inactive: null
186      */
187     private transient Reference<?> discovered;
188 
189 
190     /* High-priority thread to enqueue pending References
191      */
192     private static class ReferenceHandler extends Thread {
193 
194         private static void ensureClassInitialized(Class<?> clazz) {
195             try {
196                 Class.forName(clazz.getName(), true, clazz.getClassLoader());
197             } catch (ClassNotFoundException e) {
198                 throw (Error) new NoClassDefFoundError(e.getMessage()).initCause(e);
199             }
200         }
201 
202         static {










203             // pre-load and initialize Cleaner class so that we don't
204             // get into trouble later in the run loop if there's
205             // memory shortage while loading/initializing it lazily.
206             ensureClassInitialized(Cleaner.class);
207         }
208 
209         ReferenceHandler(ThreadGroup g, String name) {
210             super(g, null, name, 0, false);
211         }
212 
213         public void run() {
214             while (true) {
215                 processPendingReferences();
216             }
217         }
218     }
219 
220     /*
221      * Atomically get and clear (set to null) the VM's pending-Reference list.
222      */
223     private static native Reference<?> getAndClearReferencePendingList();
224 
225     /*
226      * Test whether the VM's pending-Reference list contains any entries.
227      */
228     private static native boolean hasReferencePendingList();
229 
230     /*
231      * Wait until the VM's pending-Reference list may be non-null.
232      */
233     private static native void waitForReferencePendingList();

284     //
285     // Returns true after waiting (for notification from the reference
286     // processing thread) if either (1) the VM has any pending
287     // references, or (2) the reference processing thread is
288     // processing references. Otherwise, returns false immediately.
289     private static boolean waitForReferenceProcessing()
290         throws InterruptedException
291     {
292         synchronized (processPendingLock) {
293             if (processPendingActive || hasReferencePendingList()) {
294                 // Wait for progress, not necessarily completion.
295                 processPendingLock.wait();
296                 return true;
297             } else {
298                 return false;
299             }
300         }
301     }
302 
303     static {

304         ThreadGroup tg = Thread.currentThread().getThreadGroup();
305         for (ThreadGroup tgn = tg;
306              tgn != null;
307              tg = tgn, tgn = tg.getParent());
308         Thread handler = new ReferenceHandler(tg, "Reference Handler");
309         /* If there were a special system-only priority greater than
310          * MAX_PRIORITY, it would be used here
311          */
312         handler.setPriority(Thread.MAX_PRIORITY);
313         handler.setDaemon(true);
314         handler.start();
315 
316         // provide access in SharedSecrets
317         SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {
318             @Override
319             public boolean waitForReferenceProcessing()
320                 throws InterruptedException
321             {
322                 return Reference.waitForReferenceProcessing();
323             }
324 
325             @Override
326             public void runFinalization() {
327                 Finalizer.runFinalization();
328             }





329         });
330     }
331 
332     /* -- Referent accessor and setters -- */
333 
334     /**
335      * Returns this reference object's referent.  If this reference object has
336      * been cleared, either by the program or by the garbage collector, then
337      * this method returns {@code null}.
338      *
339      * @apiNote
340      * This method returns a strong reference to the referent. This may cause
341      * the garbage collector to treat it as strongly reachable until some later
342      * collection cycle.  The {@link #refersTo(Object) refersTo} method can be
343      * used to avoid such strengthening when testing whether some object is
344      * the referent of a reference object; that is, use {@code ref.refersTo(obj)}
345      * rather than {@code ref.get() == obj}.
346      *
347      * @return   The object to which this reference refers, or
348      *           {@code null} if this reference object has been cleared

  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 jdk.internal.misc.Unsafe;
 29 import jdk.internal.misc.VM;
 30 import jdk.internal.vm.annotation.ForceInline;
 31 import jdk.internal.vm.annotation.IntrinsicCandidate;
 32 import jdk.internal.access.JavaLangRefAccess;
 33 import jdk.internal.access.SharedSecrets;
 34 import jdk.internal.ref.Cleaner;
 35 
 36 /**
 37  * Abstract base class for reference objects.  This class defines the
 38  * operations common to all reference objects.  Because reference objects are
 39  * implemented in close cooperation with the garbage collector, this class may
 40  * not be subclassed directly.
 41  *
 42  * @author   Mark Reinhold
 43  * @since    1.2
 44  */
 45 
 46 public abstract class Reference<T> {
 47 
 48     /* The state of a Reference object is characterized by two attributes.  It
 49      * may be either "active", "pending", or "inactive".  It may also be

176 
177     /* Used by the garbage collector to accumulate Reference objects that need
178      * to be revisited in order to decide whether they should be notified.
179      * Also used as the link in the pending-Reference list.  The discovered
180      * field and the next field are distinct to allow the enqueue() method to
181      * be applied to a Reference object while it is either in the
182      * pending-Reference list or in the garbage collector's discovered set.
183      *
184      * When active: null or next element in a discovered reference list
185      *              maintained by the GC (or this if last)
186      *     pending: next element in the pending-Reference list (null if last)
187      *    inactive: null
188      */
189     private transient Reference<?> discovered;
190 
191 
192     /* High-priority thread to enqueue pending References
193      */
194     private static class ReferenceHandler extends Thread {
195 
196         ReferenceHandler(ThreadGroup g, String name) {
197             super(g, null, name, 0, false);




198         }
199 
200         public void run() {
201 
202             // delay until init phase 1 completes
203             while (VM.initLevel() < 1) {
204                 try {
205                     VM.awaitInitLevel(1);
206                 } catch (InterruptedException x) {
207                     // ignore and continue
208                 }
209             }
210 
211             // pre-load and initialize Cleaner class so that we don't
212             // get into trouble later in the run loop if there's
213             // memory shortage while loading/initializing it lazily.
214             Unsafe.getUnsafe().ensureClassInitialized(Cleaner.class);

215 





216             while (true) {
217                 processPendingReferences();
218             }
219         }
220     }
221 
222     /*
223      * Atomically get and clear (set to null) the VM's pending-Reference list.
224      */
225     private static native Reference<?> getAndClearReferencePendingList();
226 
227     /*
228      * Test whether the VM's pending-Reference list contains any entries.
229      */
230     private static native boolean hasReferencePendingList();
231 
232     /*
233      * Wait until the VM's pending-Reference list may be non-null.
234      */
235     private static native void waitForReferencePendingList();

286     //
287     // Returns true after waiting (for notification from the reference
288     // processing thread) if either (1) the VM has any pending
289     // references, or (2) the reference processing thread is
290     // processing references. Otherwise, returns false immediately.
291     private static boolean waitForReferenceProcessing()
292         throws InterruptedException
293     {
294         synchronized (processPendingLock) {
295             if (processPendingActive || hasReferencePendingList()) {
296                 // Wait for progress, not necessarily completion.
297                 processPendingLock.wait();
298                 return true;
299             } else {
300                 return false;
301             }
302         }
303     }
304 
305     static {
306         @SuppressWarnings("deprecation")
307         ThreadGroup tg = Thread.currentThread().getThreadGroup();
308         for (ThreadGroup tgn = tg;
309              tgn != null;
310              tg = tgn, tgn = tg.getParent());
311         Thread handler = new ReferenceHandler(tg, "Reference Handler");
312         /* If there were a special system-only priority greater than
313          * MAX_PRIORITY, it would be used here
314          */
315         handler.setPriority(Thread.MAX_PRIORITY);
316         handler.setDaemon(true);
317         handler.start();
318 
319         // provide access in SharedSecrets
320         SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {
321             @Override
322             public boolean waitForReferenceProcessing()
323                 throws InterruptedException
324             {
325                 return Reference.waitForReferenceProcessing();
326             }
327 
328             @Override
329             public void runFinalization() {
330                 Finalizer.runFinalization();
331             }
332 
333             @Override
334             public <T> ReferenceQueue<T> newNativeReferenceQueue() {
335                 return new NativeReferenceQueue<T>();
336             }
337         });
338     }
339 
340     /* -- Referent accessor and setters -- */
341 
342     /**
343      * Returns this reference object's referent.  If this reference object has
344      * been cleared, either by the program or by the garbage collector, then
345      * this method returns {@code null}.
346      *
347      * @apiNote
348      * This method returns a strong reference to the referent. This may cause
349      * the garbage collector to treat it as strongly reachable until some later
350      * collection cycle.  The {@link #refersTo(Object) refersTo} method can be
351      * used to avoid such strengthening when testing whether some object is
352      * the referent of a reference object; that is, use {@code ref.refersTo(obj)}
353      * rather than {@code ref.get() == obj}.
354      *
355      * @return   The object to which this reference refers, or
356      *           {@code null} if this reference object has been cleared
< prev index next >