--- old/src/java.base/share/classes/java/lang/ref/Finalizer.java 2015-07-03 16:04:57.040710895 +0200 +++ new/src/java.base/share/classes/java/lang/ref/Finalizer.java 2015-07-03 16:04:56.966710382 +0200 @@ -25,85 +25,57 @@ 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 { /* Package-private; must be in - same package as the Reference - class */ - - private static ReferenceQueue queue = new ReferenceQueue<>(); - private static Finalizer unfinalized = null; - private static final Object lock = new Object(); - - private Finalizer - next = null, - prev = null; - - private boolean hasBeenFinalized() { - return (next == this); - } - - private void add() { - synchronized (lock) { - if (unfinalized != null) { - this.next = unfinalized; - unfinalized.prev = this; - } - unfinalized = this; - } - } +import java.security.AccessController; +import java.security.PrivilegedAction; - 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; - } - } +/* Package-private; must be in same package as the Reference class */ +class Finalizer extends FinalReference implements Cleaner { - private Finalizer(Object finalizee) { - super(finalizee, queue); - add(); + Finalizer(T finalizee) { + super(finalizee, null); } - /* Invoked by VM */ + /** Invoked by VM for objects overriding finalize() method */ static void register(Object finalizee) { - new Finalizer(finalizee); + Finalizer finalizer = new Finalizer<>(finalizee); + finalizer.link(); } - private void runFinalizer(JavaLangAccess jla) { - synchronized (this) { - if (hasBeenFinalized()) return; - remove(); + @Override + public void clean() { + T finalizee = delete(); + if (finalizee == null) { + return; } + unlink(); try { - Object finalizee = this.get(); - if (finalizee != null && !(finalizee instanceof java.lang.Enum)) { - jla.invokeFinalize(finalizee); - - /* Clear stack slot containing this variable, to decrease - the chances of false retention with a conservative GC */ - finalizee = null; + if (!(finalizee instanceof java.lang.Enum)) { + invokeFinalizee(finalizee); } } catch (Throwable x) { } - super.clear(); + finalizee = null; + } + + /* Invoke the finalize() method on the finalizee (overridden by Finalizator) */ + void invokeFinalizee(T finalizee) throws Throwable { + SharedSecrets.getJavaLangAccess().invokeFinalize(finalizee); + finalizee = null; + } + + @Override + public void clear() { + T finalizee = delete(); + if (finalizee == null) { + return; + } + unlink(); + /* Clear stack slot containing this variable, to decrease + the chances of false retention with a conservative GC */ + finalizee = null; } /* Create a privileged secondary finalizer thread in the system thread @@ -150,13 +122,8 @@ // 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(); } }); } @@ -173,61 +140,78 @@ // 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"); - } - 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 - } - } - final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); - running = true; - for (;;) { - try { - Finalizer f = (Finalizer)queue.remove(); - f.runFinalizer(jla); - } catch (InterruptedException x) { - // ignore and continue - } - } - } + /** + * 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; } - 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(); + // 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; + } + + 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); + } + + 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 fc = Finalizer.class; + PREV_DLL = UNSAFE.objectFieldOffset(fc.getDeclaredField("prevDll")); + NEXT_DLL = UNSAFE.objectFieldOffset(fc.getDeclaredField("nextDll")); + } catch (Exception e) { + throw new Error(e); + } + } }