Graceful Shutdown in Spring Boot: Handling Linux kill Signals, JVM SignalHandler, and Runtime Shutdown Hooks

The article explains how to perform a graceful shutdown of Spring Boot applications by handling Linux kill signals, using the JVM's SignalHandler and Runtime.addShutdownHook mechanisms, and leveraging Spring's ContextClosedEvent and the actuator shutdown endpoint, with detailed code examples and configuration tips.

Top Architect
Top Architect
Top Architect
Graceful Shutdown in Spring Boot: Handling Linux kill Signals, JVM SignalHandler, and Runtime Shutdown Hooks

This article discusses how to achieve a graceful shutdown of Java applications, focusing on Spring Boot, by handling Linux kill signals, utilizing the JVM's SignalHandler, and registering shutdown hooks with Runtime.addShutdownHook.

It explains the difference between kill -9 pid (forceful termination) and kill -15 pid (graceful termination), and lists common signal names and numbers for both Linux and Windows environments.

#查看jvm进程pid
jps
#列出所有信号名称
kill -l
# Windows下信号常量值
# INT   SIGINT     2   Ctrl+C中断
# ILL   SIGILL     4   非法指令
# FPE   SIGFPE     8   floating point exception
# SEGV  SIGSEGV    11  segment violation
# TERM  SIGTERM    5   Software termination signal from kill
# BREAK SIGBREAK   21  Ctrl-Break sequence
# ABRT  SIGABRT    22  abnormal termination triggered by abort call
# linux信号常量值
# HUP   SIGHUP     1   终端断线
# INT   SIGINT     2   中断(同 Ctrl + C)
# QUIT  SIGQUIT    3   退出(同 Ctrl + \)
# KILL  SIGKILL    9   强制终止
# TERM  SIGTERM    15  终止
# CONT  SIGCONT    18  继续(与STOP相反)
# STOP  SIGSTOP    19  暂停(同 Ctrl + Z)
# ...
# kill -9 pid   // force kill
# kill -15 pid  // graceful termination

The JVM processes these signals through a custom SignalHandler loaded at startup. The following interface and a sample implementation illustrate how the handler intercepts signals and triggers shutdown logic.

public interface SignalHandler {
    SignalHandler SIG_DFL = new NativeSignalHandler(0L);
    SignalHandler SIG_IGN = new NativeSignalHandler(1L);
    void handle(Signal var1);
}

class Terminator {
    private static SignalHandler handler = null;
    static void setup() {
        if (handler == null) {
            SignalHandler var0 = new SignalHandler() {
                public void handle(Signal var1) {
                    Shutdown.exit(var1.getNumber() + 128);
                }
            };
            handler = var0;
            try { Signal.handle(new Signal("INT"), var0); } catch (IllegalArgumentException e) {}
            try { Signal.handle(new Signal("TERM"), var0); } catch (IllegalArgumentException e) {}
        }
    }
}

Java also provides Runtime.addShutdownHook(Thread hook) to register a hook that runs when the JVM is shutting down. The hook can perform cleanup tasks before the process exits.

public class Runtime {
    public void addShutdownHook(Thread hook) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("shutdownHooks"));
        }
        ApplicationShutdownHooks.add(hook);
    }
}

Spring integrates with these mechanisms via ContextClosedEvent and the LifecycleProcessor.onClose method, which stop beans, publish shutdown events, and clean up resources. The abstract application context registers its own shutdown hook that invokes doClose() when the JVM terminates.

public abstract class AbstractApplicationContext extends DefaultResourceLoader {
    public void registerShutdownHook() {
        if (this.shutdownHook == null) {
            this.shutdownHook = new Thread() {
                @Override public void run() { doClose(); }
            };
            Runtime.getRuntime().addShutdownHook(this.shutdownHook);
        }
    }
    protected void doClose() {
        // publish ContextClosedEvent, stop Lifecycle beans, destroy beans, etc.
    }
}

Spring Boot adds a convenient REST endpoint via the spring-boot-starter-actuator module. Sending a POST request to /shutdown triggers the same shutdown sequence, optionally protected by Spring Security or network restrictions.

# Enable shutdown endpoint
endpoints.shutdown.enabled=true
# Disable password protection (for demo)
endpoints.shutdown.sensitive=false
management.context-path=/manage
management.port=8088
management.address=127.0.0.1

The underlying implementation of the actuator endpoint calls AbstractApplicationContext.close() in a separate thread, ensuring the application shuts down gracefully while returning a JSON response indicating the shutdown status.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

spring-bootGraceful ShutdownJVM SignalHandlerLinux killRuntime Shutdown Hook
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

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.