classApplicationShutdownHooks { /* The set of registered hooks */ privatestatic IdentityHashMap<Thread, Thread> hooks; static { try { Shutdown.add(1/* shutdown hook invocation order */, false/* not registered if shutdown in progress */, newRunnable() { publicvoidrun() { runHooks(); } } ); hooks = newIdentityHashMap<>(); } catch (IllegalStateException e) { // application shutdown hooks cannot be added if // shutdown is in progress. hooks = null; } }
privateApplicationShutdownHooks() {}
/* Add a new shutdown hook. Checks the shutdown state and the hook itself, * but does not do any security checks. */ staticsynchronizedvoidadd(Thread hook) { if(hooks == null) thrownewIllegalStateException("Shutdown in progress");
if (hook.isAlive()) thrownewIllegalArgumentException("Hook already running");
if (hooks.containsKey(hook)) thrownewIllegalArgumentException("Hook previously registered");
hooks.put(hook, hook); }
/* Remove a previously-registered hook. Like the add method, this method * does not do any security checks. */ staticsynchronizedbooleanremove(Thread hook) { if(hooks == null) thrownewIllegalStateException("Shutdown in progress");
if (hook == null) thrownewNullPointerException();
return hooks.remove(hook) != null; }
/* Iterates over all application hooks creating a new thread for each * to run in. Hooks are run concurrently and this method waits for * them to finish. */ staticvoidrunHooks() { Collection<Thread> threads; synchronized(ApplicationShutdownHooks.class) { threads = hooks.keySet(); hooks = null; }
23:33:11,102 INFO [main] (RzLogger.java:12) - found shutdownHook: Thread-2 23:33:11,106 INFO [main] (RzLogger.java:12) - found shutdownHook: Thread-0 23:33:11,106 INFO [main] (RzLogger.java:12) - found shutdownHook: Thread-1 exit03 exit01 exit02