You are confusing Shutdown.runHooks()
and ApplicationShutdownHooks.runHooks()
. The shutdown hooks you register with Runtime
are registered with ApplicationShutdownHooks
, which itself registers a Runnable
as a Shutdown
hook
static {
try {
Shutdown.add(1 /* shutdown hook invocation order */,
false /* not registered if shutdown in progress */,
new Runnable() {
public void run() {
runHooks(); // (!!) your hooks
}
}
);
hooks = new IdentityHashMap<>();
} catch (IllegalStateException e) {
// application shutdown hooks cannot be added if
// shutdown is in progress.
hooks = null;
}
}
The shutdown hooks are ran concurrently
static void runHooks() { // In ApplicationShutdownHooks
Collection<Thread> threads;
synchronized(ApplicationShutdownHooks.class) {
threads = hooks.keySet();
hooks = null;
}
for (Thread hook : threads) { // (!!) your hooks
hook.start();
}
for (Thread hook : threads) {
try {
hook.join();
} catch (InterruptedException x) { }
}
}
For reference, the (oracle jdk7) code for Runtime#addShutdownHook(Thread)
.
public void addShutdownHook(Thread hook) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("shutdownHooks"));
}
ApplicationShutdownHooks.add(hook);
}