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