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