8290036: Define and specify Runtime shutdown sequence
Reviewed-by: dholmes, alanb
This commit is contained in:
parent
0ec18382b7
commit
d4142d8441
@ -44,10 +44,73 @@ import jdk.internal.reflect.Reflection;
|
||||
* {@code Runtime} that allows the application to interface with
|
||||
* the environment in which the application is running. The current
|
||||
* runtime can be obtained from the {@code getRuntime} method.
|
||||
* <p>
|
||||
* An application cannot create its own instance of this class.
|
||||
*
|
||||
* <p>An application cannot create its own instance of this class.
|
||||
*
|
||||
* <h2><a id="shutdown">Shutdown Sequence</a></h2>
|
||||
*
|
||||
* <p>The Java Virtual Machine initiates the <i>shutdown sequence</i> in response
|
||||
* to one of several events:
|
||||
* <ol>
|
||||
* <li>when the number of {@linkplain Thread#isAlive() live} non-daemon threads drops to zero
|
||||
* for the first time (see note below on the JNI Invocation API);</li>
|
||||
* <li>when the {@link #exit Runtime.exit} or {@link System#exit System.exit} method is called
|
||||
* for the first time; or</li>
|
||||
* <li>when some external event occurs, such as an interrupt or a signal is received from
|
||||
* the operating system.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>At the beginning of the shutdown sequence, the registered shutdown hooks are
|
||||
* {@linkplain Thread#start started} in some unspecified order. They run concurrently
|
||||
* with any daemon or non-daemon threads that were {@linkplain Thread#isAlive() alive}
|
||||
* at the beginning of the shutdown sequence.
|
||||
*
|
||||
* <p>After the shutdown sequence has begun, registration and de-registration of shutdown hooks
|
||||
* with {@link #addShutdownHook addShutdownHook} and {@link #removeShutdownHook removeShutdownHook}
|
||||
* is prohibited. However, creating and starting new threads is permitted. New threads run
|
||||
* concurrently with the registered shutdown hooks and with any daemon or non-daemon threads
|
||||
* that are already running.
|
||||
*
|
||||
* <p>The shutdown sequence finishes when all shutdown hooks have terminated. At this point,
|
||||
* the Java Virtual Machine terminates as described below.
|
||||
*
|
||||
* <p>It is possible that one or more shutdown hooks do not terminate, for example, because
|
||||
* of an infinite loop. In this case, the shutdown sequence will never finish. Other threads
|
||||
* and shutdown hooks continue to run and can terminate the JVM via the {@link #halt halt} method.
|
||||
*
|
||||
* <p>Prior to the beginning of the shutdown sequence, it is possible for a program to start
|
||||
* a shutdown hook by calling its {@link Thread#start start} method explicitly. If this occurs, the
|
||||
* behavior of the shutdown sequence is unspecified.
|
||||
*
|
||||
* <h2><a id="termination">Java Virtual Machine Termination</a></h2>
|
||||
*
|
||||
* <p>The JVM terminates when the shutdown sequence finishes or when {@link #halt halt} is called.
|
||||
* In contrast to {@link #exit exit}, the {@link #halt halt} method does not initiate the
|
||||
* shutdown sequence.
|
||||
*
|
||||
* <p>When the JVM terminates, all threads are immediately prevented from executing any further
|
||||
* Java code. This includes shutdown hooks as well as daemon and non-daemon threads. The
|
||||
* threads' current methods do not complete normally or abruptly; no {@code finally} clause
|
||||
* of any method is executed, nor is any {@linkplain Thread.UncaughtExceptionHandler
|
||||
* uncaught exception handler}.
|
||||
*
|
||||
* @implNote
|
||||
* Native code typically uses the
|
||||
* <a href="{@docRoot}/../specs/jni/invocation.html">JNI Invocation API</a>
|
||||
* to control launching and termination of the JVM. Such native code invokes the
|
||||
* <a href="{@docRoot}/../specs/jni/invocation.html#jni_createjavavm">{@code JNI_CreateJavaVM}</a>
|
||||
* function to launch the JVM. Subsequently, the native code invokes the
|
||||
* <a href="{@docRoot}/../specs/jni/invocation.html#destroyjavavm">{@code DestroyJavaVM}</a>
|
||||
* function to await termination of that JVM. The {@code DestroyJavaVM} function is responsible
|
||||
* for initiating the shutdown sequence when the number of {@linkplain Thread#isAlive() live}
|
||||
* non-daemon threads first drops to zero. When the shutdown sequence completes and the JVM
|
||||
* terminates, control is returned to the native code that invoked {@code DestroyJavaVM}. This
|
||||
* behavior differs from the {@link #exit exit} or {@link #halt halt} methods. These methods
|
||||
* typically terminate the OS process hosting the JVM and do not interact with the JNI Invocation
|
||||
* API.
|
||||
*
|
||||
* @see java.lang.Runtime#getRuntime()
|
||||
* @jls 12.8 Program Exit
|
||||
* @since 1.0
|
||||
*/
|
||||
|
||||
@ -72,21 +135,19 @@ public class Runtime {
|
||||
private Runtime() {}
|
||||
|
||||
/**
|
||||
* Terminates the currently running Java virtual machine by initiating its
|
||||
* shutdown sequence. This method never returns normally. The argument
|
||||
* serves as a status code; by convention, a nonzero status code indicates
|
||||
* abnormal termination.
|
||||
*
|
||||
* <p> All registered {@linkplain #addShutdownHook shutdown hooks}, if any,
|
||||
* are started in some unspecified order and allowed to run concurrently
|
||||
* until they finish. Once this is done the virtual machine
|
||||
* {@linkplain #halt halts}.
|
||||
* Initiates the <a href="#shutdown">shutdown sequence</a> of the Java Virtual Machine.
|
||||
* This method blocks indefinitely; it never returns or throws an exception (that is, it
|
||||
* does not complete either normally or abruptly). The argument serves as a status code;
|
||||
* by convention, a nonzero status code indicates abnormal termination.
|
||||
*
|
||||
* <p> Invocations of this method are serialized such that only one
|
||||
* invocation will actually proceed with the shutdown sequence and
|
||||
* terminate the VM with the given status code. All other invocations
|
||||
* will block indefinitely. If this method is invoked from a shutdown
|
||||
* hook the system will deadlock.
|
||||
* simply block indefinitely.
|
||||
*
|
||||
* <p> Because this method always blocks indefinitely, if it is invoked from
|
||||
* a shutdown hook, it will prevent that shutdown hook from terminating.
|
||||
* Consequently, this will prevent the shutdown sequence from finishing.
|
||||
*
|
||||
* <p> The {@link System#exit(int) System.exit} method is the
|
||||
* conventional and convenient means of invoking this method.
|
||||
@ -118,85 +179,46 @@ public class Runtime {
|
||||
/**
|
||||
* Registers a new virtual-machine shutdown hook.
|
||||
*
|
||||
* <p> The Java virtual machine <i>shuts down</i> in response to two kinds
|
||||
* of events:
|
||||
* <p> A <i>shutdown hook</i> is simply an initialized but unstarted thread. Shutdown hooks
|
||||
* are started at the beginning of the <a href="#shutdown">shutdown sequence</a>.
|
||||
* Registration and de-registration of shutdown hooks is disallowed once the shutdown
|
||||
* sequence has begun.
|
||||
* <p>
|
||||
* Uncaught exceptions are handled in shutdown hooks just as in any other thread, as
|
||||
* specified in {@link Thread.UncaughtExceptionHandler}. After the uncaught exception
|
||||
* handler has completed, the shutdown hook is considered to have terminated and is not
|
||||
* treated differently from a hook that has terminated without having thrown an
|
||||
* uncaught exception.
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li> The program <i>exits</i> normally, when the last non-daemon
|
||||
* thread exits or when the {@link #exit exit} (equivalently,
|
||||
* {@link System#exit(int) System.exit}) method is invoked, or
|
||||
*
|
||||
* <li> The virtual machine is <i>terminated</i> in response to a
|
||||
* user interrupt, such as typing {@code ^C}, or a system-wide event,
|
||||
* such as user logoff or system shutdown.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p> A <i>shutdown hook</i> is simply an initialized but unstarted
|
||||
* thread. When the virtual machine begins its shutdown sequence it will
|
||||
* start all registered shutdown hooks in some unspecified order and let
|
||||
* them run concurrently. When all the hooks have finished it will then
|
||||
* halt. Note that daemon threads will continue to run during the shutdown
|
||||
* sequence, as will non-daemon threads if shutdown was initiated by
|
||||
* invoking the {@link #exit exit} method.
|
||||
*
|
||||
* <p> Once the shutdown sequence has begun it can be stopped only by
|
||||
* invoking the {@link #halt halt} method, which forcibly
|
||||
* terminates the virtual machine.
|
||||
*
|
||||
* <p> Once the shutdown sequence has begun it is impossible to register a
|
||||
* new shutdown hook or de-register a previously-registered hook.
|
||||
* Attempting either of these operations will cause an
|
||||
* {@link IllegalStateException} to be thrown.
|
||||
*
|
||||
* <p> Shutdown hooks run at a delicate time in the life cycle of a virtual
|
||||
* machine and should therefore be coded defensively. They should, in
|
||||
* @apiNote
|
||||
* Shutdown hooks run at a delicate time in the life cycle of a virtual
|
||||
* machine and should therefore be coded defensively. They should, in
|
||||
* particular, be written to be thread-safe and to avoid deadlocks insofar
|
||||
* as possible. They should also not rely blindly upon services that may
|
||||
* have registered their own shutdown hooks and therefore may themselves in
|
||||
* the process of shutting down. Attempts to use other thread-based
|
||||
* as possible. They should also not rely blindly upon services that may
|
||||
* have registered their own shutdown hooks and therefore may themselves be
|
||||
* in the process of shutting down. Attempts to use other thread-based
|
||||
* services such as the AWT event-dispatch thread, for example, may lead to
|
||||
* deadlocks.
|
||||
*
|
||||
* <p> Shutdown hooks should also finish their work quickly. When a
|
||||
* program invokes {@link #exit exit} the expectation is
|
||||
* <p>
|
||||
* Shutdown hooks should also finish their work quickly. When a
|
||||
* program invokes {@link #exit exit}, the expectation is
|
||||
* that the virtual machine will promptly shut down and exit. When the
|
||||
* virtual machine is terminated due to user logoff or system shutdown the
|
||||
* underlying operating system may only allow a fixed amount of time in
|
||||
* which to shut down and exit. It is therefore inadvisable to attempt any
|
||||
* underlying operating system may only allow a limited amount of time in
|
||||
* which to shut down and exit. It is therefore inadvisable to attempt any
|
||||
* user interaction or to perform a long-running computation in a shutdown
|
||||
* hook.
|
||||
*
|
||||
* <p> Uncaught exceptions are handled in shutdown hooks just as in any
|
||||
* other thread, by invoking the
|
||||
* {@link ThreadGroup#uncaughtException uncaughtException} method of the
|
||||
* thread's {@link ThreadGroup} object. The default implementation of this
|
||||
* method prints the exception's stack trace to {@link System#err} and
|
||||
* terminates the thread; it does not cause the virtual machine to exit or
|
||||
* halt.
|
||||
*
|
||||
* <p> In rare circumstances the virtual machine may <i>abort</i>, that is,
|
||||
* stop running without shutting down cleanly. This occurs when the
|
||||
* virtual machine is terminated externally, for example with the
|
||||
* {@code SIGKILL} signal on Unix or the {@code TerminateProcess} call on
|
||||
* Microsoft Windows. The virtual machine may also abort if a native
|
||||
* method goes awry by, for example, corrupting internal data structures or
|
||||
* attempting to access nonexistent memory. If the virtual machine aborts
|
||||
* then no guarantee can be made about whether or not any shutdown hooks
|
||||
* will be run.
|
||||
*
|
||||
* @param hook
|
||||
* An initialized but unstarted {@link Thread} object
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the specified hook has already been registered,
|
||||
* or if it can be determined that the hook is already running or
|
||||
* has already been run
|
||||
* If the same hook (compared using {@code ==}) as the specified hook has
|
||||
* already been registered, or if it can be determined that the hook is
|
||||
* already running or has already been run
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If the virtual machine is already in the process
|
||||
* of shutting down
|
||||
* If the shutdown sequence has already begun
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If a security manager is present and it denies
|
||||
@ -218,6 +240,9 @@ public class Runtime {
|
||||
|
||||
/**
|
||||
* De-registers a previously-registered virtual-machine shutdown hook.
|
||||
* Hooks are compared using {@code ==}.
|
||||
* Registration and de-registration of shutdown hooks is disallowed
|
||||
* once the shutdown sequence has begun.
|
||||
*
|
||||
* @param hook the hook to remove
|
||||
* @return {@code true} if the specified hook had previously been
|
||||
@ -225,8 +250,7 @@ public class Runtime {
|
||||
* otherwise.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If the virtual machine is already in the process of shutting
|
||||
* down
|
||||
* If the shutdown sequence has already begun
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If a security manager is present and it denies
|
||||
@ -246,14 +270,15 @@ public class Runtime {
|
||||
}
|
||||
|
||||
/**
|
||||
* Forcibly terminates the currently running Java virtual machine. This
|
||||
* method never returns normally.
|
||||
* Immediately <a href="#termination">terminates</a> the Java Virtual Machine. Termination
|
||||
* is unconditional and immediate. This method does not initiate the
|
||||
* <a href="#shutdown">shutdown sequence</a>, nor does it wait for the shutdown sequence
|
||||
* to finish if it is already in progress. This method never returns normally.
|
||||
*
|
||||
* <p> This method should be used with extreme caution. Unlike the
|
||||
* {@link #exit exit} method, this method does not cause shutdown
|
||||
* hooks to be started. If the shutdown sequence has already been
|
||||
* initiated then this method does not wait for any running
|
||||
* shutdown hooks to finish their work.
|
||||
* @apiNote
|
||||
* This method should be used with extreme caution. Using it may circumvent or disrupt
|
||||
* any cleanup actions intended to be performed by shutdown hooks, possibly leading to
|
||||
* data corruption.
|
||||
*
|
||||
* @param status
|
||||
* Termination status. By convention, a nonzero status code
|
||||
|
@ -1885,24 +1885,24 @@ public final class System {
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates the currently running Java Virtual Machine. The
|
||||
* argument serves as a status code; by convention, a nonzero status
|
||||
* code indicates abnormal termination.
|
||||
* Initiates the <a href="Runtime.html#shutdown">shutdown sequence</a> of the
|
||||
* Java Virtual Machine. This method always blocks indefinitely. The argument
|
||||
* serves as a status code; by convention, a nonzero status code indicates
|
||||
* abnormal termination.
|
||||
* <p>
|
||||
* This method calls the {@code exit} method in class
|
||||
* {@code Runtime}. This method never returns normally.
|
||||
* This method calls the {@code exit} method in class {@code Runtime}. This
|
||||
* method never returns normally.
|
||||
* <p>
|
||||
* The call {@code System.exit(n)} is effectively equivalent to
|
||||
* the call:
|
||||
* The call {@code System.exit(n)} is effectively equivalent to the call:
|
||||
* <blockquote><pre>
|
||||
* Runtime.getRuntime().exit(n)
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @param status exit status.
|
||||
* @throws SecurityException
|
||||
* if a security manager exists and its {@code checkExit}
|
||||
* method doesn't allow exit with the specified status.
|
||||
* @see java.lang.Runtime#exit(int)
|
||||
* @param status exit status.
|
||||
* @throws SecurityException
|
||||
* if a security manager exists and its {@code checkExit} method
|
||||
* doesn't allow exit with the specified status.
|
||||
* @see java.lang.Runtime#exit(int)
|
||||
*/
|
||||
public static void exit(int status) {
|
||||
Runtime.getRuntime().exit(status);
|
||||
|
@ -52,7 +52,6 @@ import jdk.internal.vm.ExtentLocalContainer;
|
||||
import jdk.internal.vm.StackableScope;
|
||||
import jdk.internal.vm.ThreadContainer;
|
||||
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
import sun.nio.ch.Interruptible;
|
||||
import sun.security.util.SecurityConstants;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
@ -63,11 +62,16 @@ import static java.util.concurrent.TimeUnit.NANOSECONDS;
|
||||
* virtual machine allows an application to have multiple threads of
|
||||
* execution running concurrently.
|
||||
*
|
||||
* <p> {@code Thread} defines constructors and a {@link Builder} to create threads
|
||||
* that execute {@link Runnable} tasks. {@linkplain #start() Starting} a thread
|
||||
* schedules it to execute concurrently with the thread that caused it to start.
|
||||
* The newly started thread invokes the task's {@link Runnable#run() run} method.
|
||||
* Thread defines the {@link #join() join} method to wait for a thread to terminate.
|
||||
* <p> {@code Thread} defines constructors and a {@link Builder} to create threads.
|
||||
* {@linkplain #start() Starting} a thread schedules it to execute its {@link #run() run}
|
||||
* method. The newly started thread executes concurrently with the thread that caused
|
||||
* it to start.
|
||||
*
|
||||
* <p> A thread <i>terminates</i> if either its {@code run} method completes normally,
|
||||
* or if its {@code run} method completes abruptly and the appropriate {@linkplain
|
||||
* Thread.UncaughtExceptionHandler uncaught exception handler} completes normally or
|
||||
* abruptly. With no code left to run, the thread has completed execution. The
|
||||
* {@link #join() join} method can be used to wait for a thread to terminate.
|
||||
*
|
||||
* <p> Threads have a unique {@linkplain #threadId() identifier} and a {@linkplain
|
||||
* #getName() name}. The identifier is generated when a {@code Thread} is created
|
||||
@ -94,11 +98,9 @@ import static java.util.concurrent.TimeUnit.NANOSECONDS;
|
||||
* <p> Platform threads are designated <i>daemon</i> or <i>non-daemon</i> threads.
|
||||
* When the Java virtual machine starts up, there is usually one non-daemon
|
||||
* thread (the thread that typically calls the application's {@code main} method).
|
||||
* The Java virtual machine terminates when all started non-daemon threads have
|
||||
* terminated. Unstarted non-daemon threads do not prevent the Java virtual machine
|
||||
* from terminating. The Java virtual machine can also be terminated by invoking
|
||||
* the {@linkplain Runtime#exit(int)} method, in which case it will terminate even
|
||||
* if there are non-daemon threads still running.
|
||||
* The <a href="Runtime.html#shutdown">shutdown sequence</a> begins when all started
|
||||
* non-daemon threads have terminated. Unstarted non-daemon threads do not prevent
|
||||
* the shutdown sequence from beginning.
|
||||
*
|
||||
* <p> In addition to the daemon status, platform threads have a {@linkplain
|
||||
* #getPriority() thread priority} and are members of a {@linkplain ThreadGroup
|
||||
@ -124,9 +126,10 @@ import static java.util.concurrent.TimeUnit.NANOSECONDS;
|
||||
* <p> Virtual threads do not have a thread name by default. The {@link #getName()
|
||||
* getName} method returns the empty string if a thread name is not set.
|
||||
*
|
||||
* <p> Virtual threads are daemon threads and so do not prevent the Java virtual
|
||||
* machine from terminating. Virtual threads have a fixed {@linkplain #getPriority()
|
||||
* thread priority} that cannot be changed.
|
||||
* <p> Virtual threads are daemon threads and so do not prevent the
|
||||
* <a href="Runtime.html#shutdown">shutdown sequence</a> from beginning.
|
||||
* Virtual threads have a fixed {@linkplain #getPriority() thread priority}
|
||||
* that cannot be changed.
|
||||
*
|
||||
* <h2>Creating and starting threads</h2>
|
||||
*
|
||||
@ -2200,10 +2203,10 @@ public class Thread implements Runnable {
|
||||
|
||||
/**
|
||||
* Marks this thread as either a <i>daemon</i> or <i>non-daemon</i> thread.
|
||||
* The Java virtual machine terminates when all started non-daemon threads have
|
||||
* terminated.
|
||||
* The <a href="Runtime.html#shutdown">shutdown sequence</a> begins when all
|
||||
* started non-daemon threads have terminated.
|
||||
*
|
||||
* The daemon status of a virtual thread is always {@code true} and cannot be
|
||||
* <p> The daemon status of a virtual thread is always {@code true} and cannot be
|
||||
* changed by this method to {@code false}.
|
||||
*
|
||||
* <p> This method must be invoked before the thread is started. The behavior
|
||||
|
Loading…
x
Reference in New Issue
Block a user