How to Gracefully Shut Down a Spring Boot Application: From kill Signals to Actuator Endpoints
This article explains how to perform a graceful shutdown of Java applications by handling Linux kill signals, configuring JVM signal handlers, using Runtime shutdown hooks, and leveraging Spring's ContextClosedEvent and Spring Boot Actuator's shutdown endpoint to safely release resources and stop services.
Graceful shutdown ensures that an application releases all resources, stops threads, closes sockets, deregisters from service registries, cleans temporary files, and frees memory before the JVM terminates, preventing data loss and inconsistent states.
Linux Kill Commands
Two common commands are used to terminate processes: kill -9 pid – forces immediate termination (SIGKILL). kill -15 pid – sends SIGTERM, allowing the application to intercept the signal and shut down cleanly.
JVM Signal Handling
The JVM registers signal handlers for INT and TERM signals during startup. The SignalHandler interface maps these signals to Shutdown.exit, which triggers the shutdown sequence.
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;
Signal.handle(new Signal("INT"), var0);
Signal.handle(new Signal("TERM"), var0);
}
}
}Runtime Shutdown Hook
Java allows registration of a hook thread that runs when the JVM shuts down:
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
doClose();
}
});Spring Graceful Shutdown
Spring’s AbstractApplicationContext registers a shutdown hook and defines the doClose() method, which performs the following steps:
Log the shutdown event.
Unregister the application context from LiveBeansView.
Publish ContextClosedEvent to notify listeners.
Invoke LifecycleProcessor.onClose() to stop lifecycle beans.
Destroy singleton beans.
Close the bean factory.
Execute subclass-specific shutdown logic.
Mark the context as inactive.
protected void doClose() {
boolean actuallyClose;
synchronized (this.activeMonitor) {
actuallyClose = this.active && !this.closed;
this.closed = true;
}
if (actuallyClose) {
logger.info("Closing " + this);
LiveBeansView.unregisterApplicationContext(this);
try {
publishEvent(new ContextClosedEvent(this));
} catch (Throwable ex) {
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
}
try {
getLifecycleProcessor().onClose();
} catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
destroyBeans();
closeBeanFactory();
onClose();
synchronized (this.activeMonitor) {
this.active = false;
}
}
}Spring Boot Actuator Shutdown Endpoint
Spring Boot provides a REST endpoint via spring-boot-starter-actuator that triggers a graceful shutdown by invoking AbstractApplicationContext.close() in a separate thread.
@PostMapping(produces = {"application/vnd.spring-boot.actuator.v1+json", "application/json"})
@ResponseBody
public Object invoke() {
if (!this.getDelegate().isEnabled()) {
return new ResponseEntity(Collections.singletonMap("message", "This endpoint is disabled"), HttpStatus.NOT_FOUND);
}
return super.invoke();
}The endpoint can be enabled and secured with the following properties:
# Enable shutdown endpoint
endpoints.shutdown.enabled=true
# Disable password protection (optional)
endpoints.shutdown.sensitive=false
# Management server configuration
management.context-path=/manage
management.port=8088
management.address=127.0.0.1
# Secure shutdown with Spring Security
security.user.name=admin
security.user.password=secret
management.security.role=SUPERUSERWhen a POST request is sent to http://127.0.0.1:8088/shutdown, the actuator creates a new thread that waits briefly, then calls context.close(), executing the full Spring shutdown sequence described above.
Conclusion
By handling Linux signals, registering JVM shutdown hooks, and using Spring’s built‑in shutdown mechanisms—including the Actuator endpoint—developers can achieve reliable, graceful termination of Java services, avoiding data loss and ensuring a clean state for subsequent restarts.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
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.
