< prev index next >

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

Print this page

        

*** 23,112 **** * 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(); ! 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; ! } } ! 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; } } ! ! private Finalizer(Object finalizee) { ! super(finalizee, queue); ! add(); } ! /* Invoked by VM */ ! static void register(Object finalizee) { ! new Finalizer(finalizee); } ! private void runFinalizer(JavaLangAccess jla) { ! synchronized (this) { ! if (hasBeenFinalized()) return; ! remove(); } ! 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; } - } 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. --- 23,88 ---- * questions. */ package java.lang.ref; import sun.misc.ManagedLocalsThread; import sun.misc.SharedSecrets; import sun.misc.VM; ! import java.security.AccessController; ! import java.security.PrivilegedAction; ! /* Package-private; must be in same package as the Reference class */ ! class Finalizer<T> extends FinalReference<T> implements Cleaner { ! private final int listIndex; ! Finalizer(T finalizee, int listIndex) { ! super(finalizee, null); ! this.listIndex = listIndex; } ! /** Invoked by VM for objects overriding finalize() method */ ! static void register(Object finalizee) { ! int rnd = nextSecondarySeed(); ! int index = (rnd >>> 1) & (uncleaned.length - 1); ! uncleaned[index].link(new Finalizer<>(finalizee, index), (rnd & 1) == 0); } ! @Override ! public void clean() { ! T finalizee = delete(); ! if (finalizee == null) { ! return; } + uncleaned[listIndex].unlink(this); + try { + if (!(finalizee instanceof java.lang.Enum)) { + invokeFinalizee(finalizee); } ! } catch (Throwable x) { } ! 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; } ! uncleaned[listIndex].unlink(this); /* 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 group for the given Runnable, and wait for it to complete. This method is used by both runFinalization and runFinalizersOnExit.
*** 148,164 **** 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); ! } } }); } /* Invoked by java.lang.Shutdown */ --- 124,135 ---- private volatile boolean running; public void run() { // in case of recursive call to run() if (running) return; running = true; ! ReferenceHandling.runFinalization(); } }); } /* Invoked by java.lang.Shutdown */
*** 171,233 **** 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); }}}); } ! 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 } } } } ! 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(); } } --- 142,222 ---- private volatile boolean running; public void run() { // in case of recursive call to run() if (running) return; running = true; ! for (DLList uflist : uncleaned) ! for (Reference<?> f = uflist.first(); f != null; f = uflist.succ(f)) { ! ((Cleaner)f).clean(); }}}); } ! /** ! * 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; } ! // 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); ! listIndex = -1; // never registered in any list ! 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<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 >