Created
December 9, 2010 20:58
-
-
Save mwisnicki/735322 to your computer and use it in GitHub Desktop.
A pre-shutdown JVM hook
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.reflect.Field; | |
import java.util.ArrayList; | |
import java.util.List; | |
/** | |
* Sequentially executes hooks on shutdown, before any shutdown hook registered | |
* with Runtime#addShutdownHook(Thread). | |
* Not portable, tested with Sun JVM 1.6u22 | |
*/ | |
public class PreShutdown { | |
static PreShutdown INSTANCE; | |
Runnable originalHook; | |
List<Thread> preShutdownHooks = new ArrayList<Thread>(); | |
public static synchronized PreShutdown get() { | |
try { | |
if (INSTANCE == null) { | |
INSTANCE = new PreShutdown(); | |
} | |
return INSTANCE; | |
} catch (Exception ex) { | |
throw new Error(ex); | |
} | |
} | |
private PreShutdown() throws Exception { | |
Thread warmUp = new Thread(); | |
Runtime.getRuntime().addShutdownHook(warmUp); | |
Runtime.getRuntime().removeShutdownHook(warmUp); | |
Class<?> c = Class.forName("java.lang.Shutdown"); | |
Field hf = c.getDeclaredField("hooks"); | |
boolean hfa = hf.isAccessible(); | |
try { | |
hf.setAccessible(true); | |
// TODO synchronize on Shutdown.lock | |
// TODO handle shutdown in progress | |
Runnable[] hooks = (Runnable[]) hf.get(null); | |
originalHook = hooks[1]; | |
hooks[1] = new Runnable() { | |
@Override | |
public void run() { | |
runHooks(); | |
} | |
}; | |
} finally { | |
hf.setAccessible(hfa); | |
} | |
} | |
public synchronized void addHook(Thread hook) { | |
preShutdownHooks.add(hook); | |
} | |
public synchronized void removeHook(Thread hook) { | |
preShutdownHooks.remove(hook); | |
} | |
private synchronized void runHooks() { | |
// run all PreShutdown Hooks seqentially in reverse order of registration | |
for (int i = preShutdownHooks.size() - 1; i >= 0; i--) { | |
Thread hook = preShutdownHooks.get(i); | |
hook.start(); | |
try { | |
hook.join(); | |
} catch (InterruptedException ex) { | |
} | |
} | |
originalHook.run(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment