Home » openjdk-7 » java » lang » ref » [javadoc | source]

    1   /*
    2    * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.lang.ref;
   27   
   28   import java.security.PrivilegedAction;
   29   import java.security.AccessController;
   30   
   31   
   32   final class Finalizer extends FinalReference { /* Package-private; must be in
   33                                                     same package as the Reference
   34                                                     class */
   35   
   36       /* A native method that invokes an arbitrary object's finalize method is
   37          required since the finalize method is protected
   38        */
   39       static native void invokeFinalizeMethod(Object o) throws Throwable;
   40   
   41       static private ReferenceQueue queue = new ReferenceQueue();
   42       static private Finalizer unfinalized = null;
   43       static private Object lock = new Object();
   44   
   45       private Finalizer
   46           next = null,
   47           prev = null;
   48   
   49       private boolean hasBeenFinalized() {
   50           return (next == this);
   51       }
   52   
   53       private void add() {
   54           synchronized (lock) {
   55               if (unfinalized != null) {
   56                   this.next = unfinalized;
   57                   unfinalized.prev = this;
   58               }
   59               unfinalized = this;
   60           }
   61       }
   62   
   63       private void remove() {
   64           synchronized (lock) {
   65               if (unfinalized == this) {
   66                   if (this.next != null) {
   67                       unfinalized = this.next;
   68                   } else {
   69                       unfinalized = this.prev;
   70                   }
   71               }
   72               if (this.next != null) {
   73                   this.next.prev = this.prev;
   74               }
   75               if (this.prev != null) {
   76                   this.prev.next = this.next;
   77               }
   78               this.next = this;   /* Indicates that this has been finalized */
   79               this.prev = this;
   80           }
   81       }
   82   
   83       private Finalizer(Object finalizee) {
   84           super(finalizee, queue);
   85           add();
   86       }
   87   
   88       /* Invoked by VM */
   89       static void register(Object finalizee) {
   90           new Finalizer(finalizee);
   91       }
   92   
   93       private void runFinalizer() {
   94           synchronized (this) {
   95               if (hasBeenFinalized()) return;
   96               remove();
   97           }
   98           try {
   99               Object finalizee = this.get();
  100               if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
  101                   invokeFinalizeMethod(finalizee);
  102                   /* Clear stack slot containing this variable, to decrease
  103                      the chances of false retention with a conservative GC */
  104                   finalizee = null;
  105               }
  106           } catch (Throwable x) { }
  107           super.clear();
  108       }
  109   
  110       /* Create a privileged secondary finalizer thread in the system thread
  111          group for the given Runnable, and wait for it to complete.
  112   
  113          This method is used by both runFinalization and runFinalizersOnExit.
  114          The former method invokes all pending finalizers, while the latter
  115          invokes all uninvoked finalizers if on-exit finalization has been
  116          enabled.
  117   
  118          These two methods could have been implemented by offloading their work
  119          to the regular finalizer thread and waiting for that thread to finish.
  120          The advantage of creating a fresh thread, however, is that it insulates
  121          invokers of these methods from a stalled or deadlocked finalizer thread.
  122        */
  123       private static void forkSecondaryFinalizer(final Runnable proc) {
  124           AccessController.doPrivileged(
  125               new PrivilegedAction<Void>() {
  126                   public Void run() {
  127                   ThreadGroup tg = Thread.currentThread().getThreadGroup();
  128                   for (ThreadGroup tgn = tg;
  129                        tgn != null;
  130                        tg = tgn, tgn = tg.getParent());
  131                   Thread sft = new Thread(tg, proc, "Secondary finalizer");
  132                   sft.start();
  133                   try {
  134                       sft.join();
  135                   } catch (InterruptedException x) {
  136                       /* Ignore */
  137                   }
  138                   return null;
  139                   }});
  140       }
  141   
  142       /* Called by Runtime.runFinalization() */
  143       static void runFinalization() {
  144           forkSecondaryFinalizer(new Runnable() {
  145               public void run() {
  146                   for (;;) {
  147                       Finalizer f = (Finalizer)queue.poll();
  148                       if (f == null) break;
  149                       f.runFinalizer();
  150                   }
  151               }
  152           });
  153       }
  154   
  155       /* Invoked by java.lang.Shutdown */
  156       static void runAllFinalizers() {
  157           forkSecondaryFinalizer(new Runnable() {
  158               public void run() {
  159                   for (;;) {
  160                       Finalizer f;
  161                       synchronized (lock) {
  162                           f = unfinalized;
  163                           if (f == null) break;
  164                           unfinalized = f.next;
  165                       }
  166                       f.runFinalizer();
  167                   }}});
  168       }
  169   
  170       private static class FinalizerThread extends Thread {
  171           FinalizerThread(ThreadGroup g) {
  172               super(g, "Finalizer");
  173           }
  174           public void run() {
  175               for (;;) {
  176                   try {
  177                       Finalizer f = (Finalizer)queue.remove();
  178                       f.runFinalizer();
  179                   } catch (InterruptedException x) {
  180                       continue;
  181                   }
  182               }
  183           }
  184       }
  185   
  186       static {
  187           ThreadGroup tg = Thread.currentThread().getThreadGroup();
  188           for (ThreadGroup tgn = tg;
  189                tgn != null;
  190                tg = tgn, tgn = tg.getParent());
  191           Thread finalizer = new FinalizerThread(tg);
  192           finalizer.setPriority(Thread.MAX_PRIORITY - 2);
  193           finalizer.setDaemon(true);
  194           finalizer.start();
  195       }
  196   
  197   }

Home » openjdk-7 » java » lang » ref » [javadoc | source]