< 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 >