151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.lang; 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Package-private utility class containing data structures and logic 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * governing the virtual-machine shutdown sequence. 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Mark Reinhold 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.3 361ae149ae8db46adac5723c739d53dd82a1cf2e1aPiotr Jastrzebski * @hide 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 381ae149ae8db46adac5723c739d53dd82a1cf2e1aPiotr Jastrzebski// Android-changed: Make class public. 391ae149ae8db46adac5723c739d53dd82a1cf2e1aPiotr Jastrzebskipublic class Shutdown { 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Shutdown state */ 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int RUNNING = 0; 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int HOOKS = 1; 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int FINALIZERS = 2; 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int state = RUNNING; 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Should we run all finalizers upon exit? */ 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static boolean runFinalizersOnExit = false; 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The system shutdown hooks are registered with a predefined slot. 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The list of shutdown hooks is as follows: 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // (0) Console restore hook 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // (1) Application hooks 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // (2) DeleteOnExit hook 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final int MAX_SYSTEM_HOOKS = 10; 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final Runnable[] hooks = new Runnable[MAX_SYSTEM_HOOKS]; 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // the index of the currently running shutdown hook to the hooks array 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int currentRunningHook = 0; 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* The preceding static fields are protected by this lock */ 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static class Lock { }; 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static Object lock = new Lock(); 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Lock object for the native halt method */ 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static Object haltLock = new Lock(); 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Invoked by Runtime.runFinalizersOnExit */ 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static void setRunFinalizersOnExit(boolean run) { 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (lock) { 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski runFinalizersOnExit = run; 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Add a new shutdown hook. Checks the shutdown state and the hook itself, 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * but does not do any security checks. 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The registerShutdownInProgress parameter should be false except 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * registering the DeleteOnExitHook since the first file may 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * be added to the delete on exit list by the application shutdown 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * hooks. 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 859e78cee3f3edf84254174717f475605d712aad1cNarayan Kamath * @param slot the slot in the shutdown hook array, whose element 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * will be invoked in order during shutdown 879e78cee3f3edf84254174717f475605d712aad1cNarayan Kamath * @param registerShutdownInProgress true to allow the hook 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to be registered even if the shutdown is in progress. 899e78cee3f3edf84254174717f475605d712aad1cNarayan Kamath * @param hook the hook to be registered 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 919e78cee3f3edf84254174717f475605d712aad1cNarayan Kamath * @throws IllegalStateException 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if registerShutdownInProgress is false and shutdown is in progress; or 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if registerShutdownInProgress is true and the shutdown process 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * already passes the given slot 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 96a2e3aaa5b3507c04b07ca1c80a6b3a514d3e8222Narayan Kamath // Android changed s/@params/@param 971ae149ae8db46adac5723c739d53dd82a1cf2e1aPiotr Jastrzebski public static void add(int slot, boolean registerShutdownInProgress, Runnable hook) { 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (lock) { 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (hooks[slot] != null) 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new InternalError("Shutdown hook at slot " + slot + " already registered"); 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!registerShutdownInProgress) { 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (state > RUNNING) 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalStateException("Shutdown in progress"); 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (state > HOOKS || (state == HOOKS && slot <= currentRunningHook)) 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalStateException("Shutdown in progress"); 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hooks[slot] = hook; 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Run all registered shutdown hooks 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static void runHooks() { 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i=0; i < MAX_SYSTEM_HOOKS; i++) { 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Runnable hook; 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (lock) { 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // acquire the lock to make sure the hook registered during 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // shutdown is visible here. 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski currentRunningHook = i; 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski hook = hooks[i]; 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (hook != null) hook.run(); 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch(Throwable t) { 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (t instanceof ThreadDeath) { 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ThreadDeath td = (ThreadDeath)t; 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw td; 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* The halt method is synchronized on the halt lock 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to avoid corruption of the delete-on-shutdown file list. 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * It invokes the true native halt method. 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static void halt(int status) { 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (haltLock) { 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski halt0(status); 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static native void halt0(int status); 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Wormhole for invoking java.lang.ref.Finalizer.runAllFinalizers */ 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static native void runAllFinalizers(); 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* The actual shutdown sequence is defined here. 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If it weren't for runFinalizersOnExit, this would be simple -- we'd just 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * run the hooks and then halt. Instead we need to keep track of whether 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * we're running hooks or finalizers. In the latter case a finalizer could 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * invoke exit(1) to cause immediate termination, while in the former case 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * any further invocations of exit(n), for any n, simply stall. Note that 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if on-exit finalizers are enabled they're run iff the shutdown is 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * initiated by an exit(0); they're never run on exit(n) for n != 0 or in 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * response to SIGINT, SIGTERM, etc. 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static void sequence() { 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (lock) { 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Guard against the possibility of a daemon thread invoking exit 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * after DestroyJavaVM initiates the shutdown sequence 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (state != HOOKS) return; 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski runHooks(); 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean rfoe; 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (lock) { 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski state = FINALIZERS; 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski rfoe = runFinalizersOnExit; 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (rfoe) runAllFinalizers(); 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Invoked by Runtime.exit, which does all the security checks. 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Also invoked by handlers for system-provided termination events, 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * which should pass a nonzero status code. 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static void exit(int status) { 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean runMoreFinalizers = false; 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (lock) { 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (status != 0) runFinalizersOnExit = false; 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski switch (state) { 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case RUNNING: /* Initiate shutdown */ 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski state = HOOKS; 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case HOOKS: /* Stall and halt */ 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case FINALIZERS: 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (status != 0) { 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Halt immediately on nonzero status */ 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski halt(status); 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Compatibility with old behavior: 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Run more finalizers and then halt 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski runMoreFinalizers = runFinalizersOnExit; 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (runMoreFinalizers) { 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski runAllFinalizers(); 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski halt(status); 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (Shutdown.class) { 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Synchronize on the class object, causing any other thread 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * that attempts to initiate shutdown to stall indefinitely 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sequence(); 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski halt(status); 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Invoked by the JNI DestroyJavaVM procedure when the last non-daemon 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * thread has finished. Unlike the exit method, this method does not 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * actually halt the VM. 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static void shutdown() { 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (lock) { 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski switch (state) { 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case RUNNING: /* Initiate shutdown */ 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski state = HOOKS; 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case HOOKS: /* Stall and then return */ 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski case FINALIZERS: 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (Shutdown.class) { 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sequence(); 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 242