Operations 6 min read

JVM Shutdown Methods, ShutdownHook, SignalHandler, and Graceful Shutdown Practices

The article explains the three JVM shutdown approaches—normal, forced, and abnormal—details how to use ShutdownHook and custom SignalHandler for handling termination signals, outlines best practices for graceful shutdown, and provides example scripts and references.

Zhuanzhuan Tech
Zhuanzhuan Tech
Zhuanzhuan Tech
JVM Shutdown Methods, ShutdownHook, SignalHandler, and Graceful Shutdown Practices

JVM shutdown can be categorized into three methods: normal shutdown (when the last non‑daemon thread ends, System.exit is called, or platform signals like SIGINT/SIGTERM are sent), forced shutdown (via Runtime.halt or OS kill with SIGKILL), and abnormal shutdown (triggered by RuntimeException, OOM, etc.).

ShutdownHook allows registration of cleanup code using Runtime.getRuntime().addShutdownHook(handleThread); , which runs concurrently and unordered when the JVM terminates, giving an opportunity to perform resource cleanup during normal exit or exceptions.

The registered hooks respond to signals 1 (SIGHUP) – ignored if nohup is used, 2 (SIGINT) – ignored if the process runs in background, and 15 (SIGTERM) – always responded.

Key cautions: avoid using kill -9 because it prevents Hook execution; keep Hook logic short because the system sends SIGTERM then, after a few seconds, SIGKILL; ensure Hook code is thread‑safe as multiple signals may cause concurrent executions.

Custom SignalHandler can be implemented to handle specific signals. Example: class MySignalHandler implements SignalHandler { public static void listenTo(String name) { Signal signal = new Signal(name); Signal.handle(signal, new MySignalHandler()); } public void handle(Signal signal) { System.out.println("Signal: " + signal); if (signal.toString().trim().equals("SIGTERM")) { System.out.println("SIGTERM raised, terminating..."); System.exit(1); } } } Java creates a dedicated thread for each signal, so even if the main thread is blocked, signals are still processed; the handler must be thread‑safe.

Summary of ShutdownHook behavior: it only reacts to signals 1, 2, and 15; multiple hooks execute concurrently and unordered, which can cause issues if resource cleanup has dependencies.

Graceful shutdown procedure recommended: Send kill -12 and wait 10 seconds; a custom SignalHandler processes this signal while all resources are still healthy, allowing the service to notify upstream clients and finish pending requests. Send kill -15 and wait another 10 seconds; registered ShutdownHooks run to release resources, often completing before the timeout. If the JVM is still alive, send kill -9 to force termination. The first step provides a window for orderly shutdown.

An example from the ZZSCF RPC framework demonstrates this sequence with screenshots of the shutdown flow.

A startup script demo is included, showing a typical JVM restart script with usage: . /main.sh start|stop|restart|kill|status and a link to the source code on GitHub.

References: How to gracefully handle the SIGKILL signal in Java – https://stackoverflow.com/questions/2541597/how-to-gracefully-handle-the-sigkill-signal-in-java Service graceful shutdown – https://juejin.cn/post/6844903814181421064

JavaJVMShutdownHookGracefulShutdownProcessSignalsSignalHandler
Zhuanzhuan Tech
Written by

Zhuanzhuan Tech

A platform for Zhuanzhuan R&D and industry peers to learn and exchange technology, regularly sharing frontline experience and cutting‑edge topics. We welcome practical discussions and sharing; contact waterystone with any questions.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.