Understanding Java ShutdownHook: Principles, Implementation, and Use Cases
This article explains the concept of Java's Runtime.addShutdownHook, details its underlying implementation in the Runtime and ApplicationShutdownHooks classes, demonstrates usage with code examples, discusses typical application scenarios, potential risks of long‑running hooks, and provides best‑practice recommendations for safe JVM shutdown handling.
1. Introduction: The article poses the question of how to perform actions such as closing remote connections when the JVM exits.
2. ShutdownHook Overview: It introduces Runtime.getRuntime().addShutdownHook , explaining that a shutdown hook is a thread registered to run during JVM shutdown.
3. Runtime Class: Shows the source of addShutdownHook method and its permission checks, then calls ApplicationShutdownHooks.add :
public void addShutdownHook(Thread hook) {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("shutdownHooks"));
}
ApplicationShutdownHooks.add(hook);
}4. ApplicationShutdownHooks Class: Describes the static hooks map, the add method that validates the hook, and the runHooks method that starts each hook thread and waits for its completion.
private static IdentityHashMap
hooks;
static synchronized void add(Thread hook) {
if (hooks == null) throw new IllegalStateException("Shutdown in progress");
if (hook.isAlive()) throw new IllegalArgumentException("Hook already running");
if (hooks.containsKey(hook)) throw new IllegalArgumentException("Hook previously registered");
hooks.put(hook, hook);
}
static void runHooks() {
Collection
threads;
synchronized (ApplicationShutdownHooks.class) {
threads = hooks.keySet();
hooks = null;
}
for (Thread hook : threads) {
hook.start();
}
for (Thread hook : threads) {
while (true) {
try {
hook.join();
break;
} catch (InterruptedException ignored) {}
}
}
}5. Execution Flow: Outlines the call chain System.exit → Runtime.exit → Shutdown → runHooks → ApplicationShutdownHooks.runHooks , forming a closed loop that ensures registered hooks run on normal exit.
6. Example Usage: Provides a simple program that registers a thread printing "等等我" and demonstrates the output order when the JVM terminates.
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread() {
@Override
public void run() {
System.out.println("等等我");
}
};
Runtime.getRuntime().addShutdownHook(thread);
System.out.println("程序关闭");
}Output: 程序关闭 等等我
7. Application Scenarios: Lists typical uses such as closing connections, releasing resources, and recording execution state.
8. Risks: Highlights that long‑running hook threads block JVM shutdown, illustrated with a hook that sleeps for several minutes.
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000 * 300);
} catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(new Date() + " 等我5分钟");
}
};
Runtime.getRuntime().addShutdownHook(thread);
System.out.println(new Date() + " 程序关闭");
}Output shows the main thread finishes first, then the JVM waits for the hook to complete.
9. Solutions: Suggest controlling hook execution time in code or using forced termination (kill -9) for unresponsive shutdowns.
10. Extensions: Mentions that frameworks like Spring use shutdown hooks for resource cleanup and that developers can register their own hooks for safer shutdown.
11. Conclusion: Summarizes the key points and encourages developers to apply shutdown hooks responsibly to release resources and reduce shutdown‑related risks.
JD Tech Talk
Official JD Tech public account delivering best practices and technology innovation.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.