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 */, new Runnable() { publicvoidrun(){ runHooks(); } } ); hooks = new IdentityHashMap<>(); } 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) thrownew IllegalStateException("Shutdown in progress");
if (hook.isAlive()) thrownew IllegalArgumentException("Hook already running");
if (hooks.containsKey(hook)) thrownew IllegalArgumentException("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) thrownew IllegalStateException("Shutdown in progress");
if (hook == null) thrownew NullPointerException();
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