Java Shutdown

From NovaOrdis Knowledge Base
Jump to navigation Jump to search

Internal

Playground Example

https://github.com/NovaOrdis/playground/tree/master/java/shutdown-hook

Non-Daemon Threads and "Natural" Shutdown

The JVM will "naturally" exit when only daemon threads remain. As long as there are non-daemon threads (even in WAITING, TIMED_WAITING state), the JVM will continue to live.

The simple possible "natural" JVM shutdown is to allow the main thread to run to completion, without starting any other threads. If shutdown hooks are registered, they will be executed even if the JVM dies of "natural causes" (no System.exit() call).

System.exit()

System.exit() terminates the JVM 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.

The virtual machine's shutdown sequence consists of two phases.

In the first phase all registered shutdown hooks, if any, are started in some unspecified order and allowed to run concurrently until they finish.

In the second phase all uninvoked finalizers are run if finalization-on-exit has been enabled. Once this is done the JVM halts.

If System.exit() is invoked after the virtual machine has begun its shutdown sequence then if shutdown hooks are being run this method will block indefinitely. If shutdown hooks have already been run and on-exit finalization has been enabled then this method halts the virtual machine with the given status code if the status is nonzero; otherwise, it blocks indefinitely.

Non-Daemon Threads and System.exit()

If System.exit() is explicitly invoked and the shutdown sequence initiated by System.exit() completes successfully, all non-daemon threads will be terminated.

What Happens if a Shutdown Hook Blocks?

If a shutdown hook sleeps or blocks indefinitely, the shutdown sequence of the JVM will stop.

This is a thread dump of a Java 1.6 JVM whose shutdown hook (the thread "Playground Shutdown Hook Thread") is sleeping. The shutdown sequence is on hold.

Full thread dump Java HotSpot(TM) 64-Bit Server VM (19.0-b09 mixed mode):

[...]

"Playground Shutdown Hook Thread" prio=6 tid=0x0000000006d24000 nid=0x22e8 waiting on condition [0x00000000080cf000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at playground.shutdownhook.Main$ShutdownHook.run(Main.java:53)

"main" prio=6 tid=0x000000000060d000 nid=0x1614 in Object.wait() [0x000000000253f000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x00000007ab03fe88> (a playground.shutdownhook.Main$ShutdownHook)
	at java.lang.Thread.join(Thread.java:1186)
	- locked <0x00000007ab03fe88> (a playground.shutdownhook.Main$ShutdownHook)
	at java.lang.Thread.join(Thread.java:1239)
	at java.lang.ApplicationShutdownHooks.runHooks(ApplicationShutdownHooks.java:79)
	at java.lang.ApplicationShutdownHooks$1.run(ApplicationShutdownHooks.java:24)
	at java.lang.Shutdown.runHooks(Shutdown.java:79)
	at java.lang.Shutdown.sequence(Shutdown.java:123)
	at java.lang.Shutdown.exit(Shutdown.java:168)
	- locked <0x00000006fc0b3ea8> (a java.lang.Class for java.lang.Shutdown)
	at java.lang.Runtime.exit(Runtime.java:90)
	at java.lang.System.exit(System.java:904)
	at playground.shutdownhook.Main.main(Main.java:21)

[...]

The above experiment was conducted with a non-daemon "main" thread and a non-daemon "Playground Shutdown Hook Thread". A JVM with no non-daemon active thread will simply exit, so there needs to be at least a non-daemon thread to keep the JVM alive until System.exit() is called. Configuring the shutdown hook thread to be a daemon thread has no effect on the outcome, it will still make the JVM hang until it's completed.