< prev index next >

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

Print this page

        

@@ -108,26 +108,16 @@
      *   otherwise:   NULL
      */
     private transient Reference<T> discovered;  /* used by VM */
 
 
-    /* Object used to synchronize with the garbage collector.  The collector
-     * must acquire this lock at the beginning of each collection cycle.  It is
-     * therefore critical that any code holding this lock complete as quickly
-     * as possible, allocate no new objects, and avoid calling user code.
+    /* Blocks until the reference pending list becomes non-empty and
+     * returns the list.
      */
-    private static class Lock { }
-    private static Lock lock = new Lock();
+    private static native Reference<Object> getReferencePendingList();
 
 
-    /* List of References waiting to be enqueued.  The collector adds
-     * References to this list, while the Reference-handler thread removes
-     * them.  This list is protected by the above lock object. The
-     * list uses the discovered field to link its elements.
-     */
-    private static Reference<Object> pending = null;
-
     /* High-priority thread to enqueue pending References
      */
     private static class ReferenceHandler extends Thread {
 
         private static void ensureClassInitialized(Class<?> clazz) {

@@ -137,14 +127,12 @@
                 throw (Error) new NoClassDefFoundError(e.getMessage()).initCause(e);
             }
         }
 
         static {
-            // pre-load and initialize InterruptedException and Cleaner classes
-            // so that we don't get into trouble later in the run loop if there's
-            // memory shortage while loading/initializing them lazily.
-            ensureClassInitialized(InterruptedException.class);
+            // pre-load and initialize Cleaner class so that we don't get into trouble later in
+            // the run loop if there's memory shortage while loading/initializing them lazily.
             ensureClassInitialized(Cleaner.class);
         }
 
         ReferenceHandler(ThreadGroup g, String name) {
             super(g, null, name, 0, false);

@@ -172,53 +160,44 @@
      *         was processed, or we waited for notification and either got it
      *         or thread was interrupted before being notified;
      *         {@code false} otherwise.
      */
     static boolean tryHandlePending(boolean waitForNotify) {
-        Reference<Object> r;
-        Cleaner c;
-        try {
-            synchronized (lock) {
-                if (pending != null) {
-                    r = pending;
-                    // 'instanceof' might throw OutOfMemoryError sometimes
-                    // so do this before un-linking 'r' from the 'pending' chain...
-                    c = r instanceof Cleaner ? (Cleaner) r : null;
-                    // unlink 'r' from 'pending' chain
-                    pending = r.discovered;
-                    r.discovered = null;
-                } else {
-                    // The waiting on the lock may cause an OutOfMemoryError
-                    // because it may try to allocate exception objects.
-                    if (waitForNotify) {
-                        lock.wait();
-                    }
-                    // retry if waited
-                    return waitForNotify;
-                }
-            }
-        } catch (OutOfMemoryError x) {
-            // Give other threads CPU time so they hopefully drop some live references
-            // and GC reclaims some space.
-            // Also prevent CPU intensive spinning in case 'r instanceof Cleaner' above
-            // persistently throws OOME for some time...
-            Thread.yield();
-            // retry
-            return true;
-        } catch (InterruptedException x) {
-            // retry
-            return true;
+        if (!waitForNotify) {
+            // FIXME! Calls from non-blocking helper threads not yet supported.
+            return false;
         }
 
+        // Get pending references from the VM
+        Reference<Object> pending_list = getReferencePendingList();
+
+        // Enqueue references
+        while (pending_list != null) {
+            // Unlink
+            Reference<Object> r = pending_list;
+            pending_list = r.discovered;
+            r.discovered = null;
+
         // Fast path for cleaners
-        if (c != null) {
-            c.clean();
-            return true;
+            if (r instanceof Cleaner) {
+                try {
+                    ((Cleaner)r).clean();
+                } catch (Throwable x) {
+                    // Ignored
+                }
+
+                // Don't enqueue
+                continue;
         }
 
+            // Enqueue
         ReferenceQueue<? super Object> q = r.queue;
-        if (q != ReferenceQueue.NULL) q.enqueue(r);
+            if (q != ReferenceQueue.NULL) {
+                q.enqueue(r);
+            }
+        }
+
         return true;
     }
 
     static {
         ThreadGroup tg = Thread.currentThread().getThreadGroup();
< prev index next >