< prev index next >

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

Print this page

        

@@ -23,90 +23,62 @@
  * questions.
  */
 
 package java.lang.ref;
 
-import java.security.PrivilegedAction;
-import java.security.AccessController;
-import sun.misc.JavaLangAccess;
 import sun.misc.ManagedLocalsThread;
 import sun.misc.SharedSecrets;
 import sun.misc.VM;
 
-final class Finalizer extends FinalReference<Object> { /* Package-private; must be in
-                                                          same package as the Reference
-                                                          class */
-
-    private static ReferenceQueue<Object> queue = new ReferenceQueue<>();
-    private static Finalizer unfinalized = null;
-    private static final Object lock = new Object();
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 
-    private Finalizer
-        next = null,
-        prev = null;
+/* Package-private; must be in same package as the Reference class */
+class Finalizer<T> extends FinalReference<T> implements Cleaner {
 
-    private boolean hasBeenFinalized() {
-        return (next == this);
+    Finalizer(T finalizee) {
+        super(finalizee, null);
     }
 
-    private void add() {
-        synchronized (lock) {
-            if (unfinalized != null) {
-                this.next = unfinalized;
-                unfinalized.prev = this;
-            }
-            unfinalized = this;
-        }
+    /** Invoked by VM for objects overriding finalize() method */
+    static void register(Object finalizee) {
+        Finalizer<?> finalizer = new Finalizer<>(finalizee);
+        finalizer.link();
     }
 
-    private void remove() {
-        synchronized (lock) {
-            if (unfinalized == this) {
-                if (this.next != null) {
-                    unfinalized = this.next;
-                } else {
-                    unfinalized = this.prev;
-                }
-            }
-            if (this.next != null) {
-                this.next.prev = this.prev;
-            }
-            if (this.prev != null) {
-                this.prev.next = this.next;
-            }
-            this.next = this;   /* Indicates that this has been finalized */
-            this.prev = this;
+    @Override
+    public void clean() {
+        T finalizee = delete();
+        if (finalizee == null) {
+            return;
         }
+        unlink();
+        try {
+            if (!(finalizee instanceof java.lang.Enum)) {
+                invokeFinalizee(finalizee);
     }
-
-    private Finalizer(Object finalizee) {
-        super(finalizee, queue);
-        add();
+        } catch (Throwable x) { }
+        finalizee = null;
     }
 
-    /* Invoked by VM */
-    static void register(Object finalizee) {
-        new Finalizer(finalizee);
+    /* Invoke the finalize() method on the finalizee (overridden by Finalizator) */
+    void invokeFinalizee(T finalizee) throws Throwable {
+        SharedSecrets.getJavaLangAccess().invokeFinalize(finalizee);
+        finalizee = null;
     }
 
-    private void runFinalizer(JavaLangAccess jla) {
-        synchronized (this) {
-            if (hasBeenFinalized()) return;
-            remove();
+    @Override
+    public void clear() {
+        T finalizee = delete();
+        if (finalizee == null) {
+            return;
         }
-        try {
-            Object finalizee = this.get();
-            if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
-                jla.invokeFinalize(finalizee);
-
+        unlink();
                 /* Clear stack slot containing this variable, to decrease
                    the chances of false retention with a conservative GC */
                 finalizee = null;
             }
-        } catch (Throwable x) { }
-        super.clear();
-    }
 
     /* Create a privileged secondary finalizer thread in the system thread
        group for the given Runnable, and wait for it to complete.
 
        This method is used by both runFinalization and runFinalizersOnExit.

@@ -148,17 +120,12 @@
             private volatile boolean running;
             public void run() {
                 // in case of recursive call to run()
                 if (running)
                     return;
-                final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
                 running = true;
-                for (;;) {
-                    Finalizer f = (Finalizer)queue.poll();
-                    if (f == null) break;
-                    f.runFinalizer(jla);
-                }
+                ReferenceHandling.runFinalization();
             }
         });
     }
 
     /* Invoked by java.lang.Shutdown */

@@ -171,63 +138,80 @@
             private volatile boolean running;
             public void run() {
                 // in case of recursive call to run()
                 if (running)
                     return;
-                final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
                 running = true;
-                for (;;) {
-                    Finalizer f;
-                    synchronized (lock) {
-                        f = unfinalized;
-                        if (f == null) break;
-                        unfinalized = f.next;
-                    }
-                    f.runFinalizer(jla);
+                for (DLList ucList : uncleanedLists)
+                    for (Reference<?> f = ucList.first(); f != null; f = ucList.succ(f)) {
+                        ((Cleaner)f).clean();
                 }}});
     }
 
-    private static class FinalizerThread extends ManagedLocalsThread {
-        private volatile boolean running;
-        FinalizerThread(ThreadGroup g) {
-            super(g, "Finalizer");
+    /**
+     * Atomically clear the Finalizer and return the finalizee.
+     *
+     * @return the finalizee or null
+     */
+    private T delete() {
+        T referent = getReferentVolatile();
+        return (referent != null) && casReferent(referent, null)
+               ? referent : null;
         }
-        public void run() {
-            // in case of recursive call to run()
-            if (running)
-                return;
 
-            // Finalizer thread starts before System.initializeSystemClass
-            // is called.  Wait until JavaLangAccess is available
-            while (!VM.isBooted()) {
-                // delay until VM completes initialization
-                try {
-                    VM.awaitBooted();
-                } catch (InterruptedException x) {
-                    // ignore and continue
+    // Methods and state that enable Finalizer to be an element of DLList
+
+    /** A constructor used for special Reference instances used in DLList */
+    Finalizer(boolean setPrevToSelf, boolean setNextToSelf) {
+        super(null, null);
+        if (setPrevToSelf) prevDll = this;
+        if (setNextToSelf) nextDll = this;
+    }
+
+    @SuppressWarnings("unused") // assigned through Unsafe
+    private volatile Reference<?> prevDll, nextDll;
+
+    boolean isDeletedDll() {
+        return getReferentVolatile() == null;
                 }
+
+    Reference<?> getPrevDll() {
+        return prevDll;
             }
-            final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
-            running = true;
-            for (;;) {
-                try {
-                    Finalizer f = (Finalizer)queue.remove();
-                    f.runFinalizer(jla);
-                } catch (InterruptedException x) {
-                    // ignore and continue
+
+    void lazySetPrevDll(Reference<?> val) {
+        UNSAFE.putOrderedObject(this, PREV_DLL, val);
                 }
+
+    boolean casPrevDll(Reference<?> cmp, Reference<?> val) {
+        return UNSAFE.compareAndSwapObject(this, PREV_DLL, cmp, val);
             }
+
+    Reference<?> getNextDll() {
+        return nextDll;
         }
+
+    void lazySetNextDll(Reference<?> val) {
+        UNSAFE.putOrderedObject(this, NEXT_DLL, val);
     }
 
-    static {
-        ThreadGroup tg = Thread.currentThread().getThreadGroup();
-        for (ThreadGroup tgn = tg;
-             tgn != null;
-             tg = tgn, tgn = tg.getParent());
-        Thread finalizer = new FinalizerThread(tg);
-        finalizer.setPriority(Thread.MAX_PRIORITY - 2);
-        finalizer.setDaemon(true);
-        finalizer.start();
+    boolean casNextDll(Reference<?> cmp, Reference<?> val) {
+        return UNSAFE.compareAndSwapObject(this, NEXT_DLL, cmp, val);
     }
 
+    // Unsafe machinery
+
+    private static final sun.misc.Unsafe UNSAFE;
+    private static final long PREV_DLL;
+    private static final long NEXT_DLL;
+
+    static {
+        try {
+            UNSAFE = sun.misc.Unsafe.getUnsafe();
+            Class<Finalizer> fc = Finalizer.class;
+            PREV_DLL = UNSAFE.objectFieldOffset(fc.getDeclaredField("prevDll"));
+            NEXT_DLL = UNSAFE.objectFieldOffset(fc.getDeclaredField("nextDll"));
+        } catch (Exception e) {
+            throw new Error(e);
+        }
+    }
 }
< prev index next >