- /*
- * @(#)Finalizer.java 1.17 00/02/02
- *
- * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the proprietary information of Sun Microsystems, Inc.
- * Use is subject to license terms.
- *
- */
-
- package java.lang.ref;
-
- import java.security.PrivilegedAction;
- import java.security.AccessController;
-
-
- final class Finalizer extends FinalReference { /* Package-private; must be in
- same package as the Reference
- class */
-
- /* A native method that invokes an arbitrary object's finalize method is
- required since the finalize method is protected
- */
- static native void invokeFinalizeMethod(Object o) throws Throwable;
-
- static private ReferenceQueue queue = new ReferenceQueue();
- static private Finalizer unfinalized = null;
- static private 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() {
- synchronized (this) {
- if (hasBeenFinalized()) return;
- remove();
- }
- try {
- Object finalizee = this.get();
- if (finalizee != null) {
- invokeFinalizeMethod(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.
- The former method invokes all pending finalizers, while the latter
- invokes all uninvoked finalizers if on-exit finalization has been
- enabled.
-
- These two methods could have been implemented by offloading their work
- to the regular finalizer thread and waiting for that thread to finish.
- The advantage of creating a fresh thread, however, is that it insulates
- invokers of these methods from a stalled or deadlocked finalizer thread.
- */
- private static void forkSecondaryFinalizer(final Runnable proc) {
- PrivilegedAction pa = new PrivilegedAction() {
- public Object run() {
- ThreadGroup tg = Thread.currentThread().getThreadGroup();
- for (ThreadGroup tgn = tg;
- tgn != null;
- tg = tgn, tgn = tg.getParent());
- Thread sft = new Thread(tg, proc, "Secondary finalizer");
- sft.start();
- try {
- sft.join();
- } catch (InterruptedException x) {
- /* Ignore */
- }
- return null;
- }};
- AccessController.doPrivileged(pa);
- }
-
- /* Called by Runtime.runFinalization() */
- static void runFinalization() {
- forkSecondaryFinalizer(new Runnable() {
- public void run() {
- for (;;) {
- Finalizer f = (Finalizer)queue.poll();
- if (f == null) break;
- f.runFinalizer();
- }
- }
- });
- }
-
- /* Invoked by java.lang.Shutdown */
- static void runAllFinalizers() {
- forkSecondaryFinalizer(new Runnable() {
- public void run() {
- for (;;) {
- Finalizer f;
- synchronized (lock) {
- f = unfinalized;
- if (f == null) break;
- unfinalized = f.next;
- }
- f.runFinalizer();
- }}});
- }
-
- private static class FinalizerThread extends Thread {
- FinalizerThread(ThreadGroup g) {
- super(g, "Finalizer");
- }
- public void run() {
- for (;;) {
- try {
- Finalizer f = (Finalizer)queue.remove();
- f.runFinalizer();
- } catch (InterruptedException x) {
- 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();
- }
-
- }