Save This Page
Home » openjdk-7 » java » lang » [javadoc | source]
    1   /*
    2    * Copyright 1999-2005 Sun Microsystems, Inc.  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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.lang;
   27   
   28   import java.util.ArrayList;
   29   
   30   
   31   /**
   32    * Package-private utility class containing data structures and logic
   33    * governing the virtual-machine shutdown sequence.
   34    *
   35    * @author   Mark Reinhold
   36    * @since    1.3
   37    */
   38   
   39   class Shutdown {
   40   
   41       /* Shutdown state */
   42       private static final int RUNNING = 0;
   43       private static final int HOOKS = 1;
   44       private static final int FINALIZERS = 2;
   45       private static int state = RUNNING;
   46   
   47       /* Should we run all finalizers upon exit? */
   48       private static boolean runFinalizersOnExit = false;
   49   
   50       /* The set of registered, wrapped hooks, or null if there aren't any */
   51       private static ArrayList<Runnable> hooks = new ArrayList<Runnable>();
   52   
   53       /* The preceding static fields are protected by this lock */
   54       private static class Lock { };
   55       private static Object lock = new Lock();
   56   
   57       /* Lock object for the native halt method */
   58       private static Object haltLock = new Lock();
   59   
   60       /* Invoked by Runtime.runFinalizersOnExit */
   61       static void setRunFinalizersOnExit(boolean run) {
   62           synchronized (lock) {
   63               runFinalizersOnExit = run;
   64           }
   65       }
   66   
   67   
   68       /* Add a new shutdown hook.  Checks the shutdown state and the hook itself,
   69        * but does not do any security checks.
   70        */
   71       static void add(Runnable hook) {
   72           synchronized (lock) {
   73               if (state > RUNNING)
   74                   throw new IllegalStateException("Shutdown in progress");
   75   
   76               hooks.add(hook);
   77           }
   78       }
   79   
   80   
   81       /* Remove a previously-registered hook.  Like the add method, this method
   82        * does not do any security checks.
   83        */
   84       static boolean remove(Runnable hook) {
   85           synchronized (lock) {
   86               if (state > RUNNING)
   87                   throw new IllegalStateException("Shutdown in progress");
   88               if (hook == null) throw new NullPointerException();
   89               if (hooks == null) {
   90                   return false;
   91               } else {
   92                   return hooks.remove(hook);
   93               }
   94           }
   95       }
   96   
   97   
   98       /* Run all registered shutdown hooks
   99        */
  100       private static void runHooks() {
  101           /* We needn't bother acquiring the lock just to read the hooks field,
  102            * since the hooks can't be modified once shutdown is in progress
  103            */
  104           for (Runnable hook : hooks) {
  105               try {
  106                   hook.run();
  107               } catch(Throwable t) {
  108                   if (t instanceof ThreadDeath) {
  109                       ThreadDeath td = (ThreadDeath)t;
  110                       throw td;
  111                   }
  112               }
  113           }
  114       }
  115   
  116       /* The halt method is synchronized on the halt lock
  117        * to avoid corruption of the delete-on-shutdown file list.
  118        * It invokes the true native halt method.
  119        */
  120       static void halt(int status) {
  121           synchronized (haltLock) {
  122               halt0(status);
  123           }
  124       }
  125   
  126       static native void halt0(int status);
  127   
  128       /* Wormhole for invoking java.lang.ref.Finalizer.runAllFinalizers */
  129       private static native void runAllFinalizers();
  130   
  131   
  132       /* The actual shutdown sequence is defined here.
  133        *
  134        * If it weren't for runFinalizersOnExit, this would be simple -- we'd just
  135        * run the hooks and then halt.  Instead we need to keep track of whether
  136        * we're running hooks or finalizers.  In the latter case a finalizer could
  137        * invoke exit(1) to cause immediate termination, while in the former case
  138        * any further invocations of exit(n), for any n, simply stall.  Note that
  139        * if on-exit finalizers are enabled they're run iff the shutdown is
  140        * initiated by an exit(0); they're never run on exit(n) for n != 0 or in
  141        * response to SIGINT, SIGTERM, etc.
  142        */
  143       private static void sequence() {
  144           synchronized (lock) {
  145               /* Guard against the possibility of a daemon thread invoking exit
  146                * after DestroyJavaVM initiates the shutdown sequence
  147                */
  148               if (state != HOOKS) return;
  149           }
  150           runHooks();
  151           boolean rfoe;
  152           synchronized (lock) {
  153               state = FINALIZERS;
  154               rfoe = runFinalizersOnExit;
  155           }
  156           if (rfoe) runAllFinalizers();
  157       }
  158   
  159   
  160       /* Invoked by Runtime.exit, which does all the security checks.
  161        * Also invoked by handlers for system-provided termination events,
  162        * which should pass a nonzero status code.
  163        */
  164       static void exit(int status) {
  165           boolean runMoreFinalizers = false;
  166           synchronized (lock) {
  167               if (status != 0) runFinalizersOnExit = false;
  168               switch (state) {
  169               case RUNNING:       /* Initiate shutdown */
  170                   state = HOOKS;
  171                   break;
  172               case HOOKS:         /* Stall and halt */
  173                   break;
  174               case FINALIZERS:
  175                   if (status != 0) {
  176                       /* Halt immediately on nonzero status */
  177                       halt(status);
  178                   } else {
  179                       /* Compatibility with old behavior:
  180                        * Run more finalizers and then halt
  181                        */
  182                       runMoreFinalizers = runFinalizersOnExit;
  183                   }
  184                   break;
  185               }
  186           }
  187           if (runMoreFinalizers) {
  188               runAllFinalizers();
  189               halt(status);
  190           }
  191           synchronized (Shutdown.class) {
  192               /* Synchronize on the class object, causing any other thread
  193                * that attempts to initiate shutdown to stall indefinitely
  194                */
  195               sequence();
  196               halt(status);
  197           }
  198       }
  199   
  200   
  201       /* Invoked by the JNI DestroyJavaVM procedure when the last non-daemon
  202        * thread has finished.  Unlike the exit method, this method does not
  203        * actually halt the VM.
  204        */
  205       static void shutdown() {
  206           synchronized (lock) {
  207               switch (state) {
  208               case RUNNING:       /* Initiate shutdown */
  209                   state = HOOKS;
  210                   break;
  211               case HOOKS:         /* Stall and then return */
  212               case FINALIZERS:
  213                   break;
  214               }
  215           }
  216           synchronized (Shutdown.class) {
  217               sequence();
  218           }
  219       }
  220   
  221   }

Save This Page
Home » openjdk-7 » java » lang » [javadoc | source]