Why kill -9 Can Corrupt Your Spring Boot Service and How to Shut It Down Gracefully

This article explains the dangers of using the Linux kill -9 command on Spring Boot applications, illustrates data loss scenarios, and provides multiple graceful shutdown methods—including SIGTERM, Spring's ConfigurableApplicationContext, Actuator endpoints, and custom Tomcat shutdown configurations—complete with code examples and best‑practice tips.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Why kill -9 Can Corrupt Your Spring Boot Service and How to Shut It Down Gracefully

kill -9 pid ???

The kill command sends signals to processes; the default is SIGTERM (15) which terminates a program, while SIGKILL (9) forces immediate termination. Process IDs can be obtained with ps or jobs.

Problems caused by kill -9 pid

Because kill -9 is a violent termination, it can lead to serious consequences such as data inconsistency. For example, in a money‑transfer operation using MyISAM tables, if the process is killed after debiting account A but before crediting account B, the system ends up with lost money, similar to a sudden power outage.

How to stop a project gracefully

Tomcat provides shutdown scripts ( shutdown.bat/shutdown.sh) that perform an orderly shutdown. A graceful shutdown involves four steps: stop accepting new requests, check for active threads, wait for running threads to finish, and finally stop the container.

Graceful shutdown with kill -15 pid

Sending SIGTERM (15) allows the application to handle interruption. The example creates a @GetMapping("/test") endpoint that sleeps for 100 seconds, then demonstrates stopping the process with kill -15 <pid>. The log shows that the start message is printed, the thread is interrupted, and the end message appears.

@GetMapping(value = "/test")
public String test() {
    log.info("test --- start");
    try {
        Thread.sleep(100000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    log.info("test --- end");
    return "test";
}

ConfigurableApplicationContext close

Implementing a shutdown endpoint that casts the Spring ApplicationContext to ConfigurableApplicationContext and calls close() stops the Spring Boot application.

package com.ymy.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class TestController implements ApplicationContextAware {
    private ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.context = applicationContext;
    }

    @PostMapping(value = "shutdown")
    public void shutdown() {
        ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) context;
        ctx.close();
    }
}

Actuator shutdown

Adding the spring-boot-starter-actuator dependency and enabling the shutdown endpoint in application.yml provides a RESTful way to stop the service.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
server:
  port: 9988

management:
  endpoints:
    web:
      exposure:
        include: shutdown
  endpoint:
    shutdown:
      enabled: true

ElegantShutdownConfig

A custom Tomcat connector customizer pauses new requests, waits for the thread pool to finish, and optionally forces termination after a configurable wait time.

package com.ymy.config;

import org.apache.catalina.connector.Connector;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ElegantShutdownConfig implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
    private volatile Connector connector;
    private final int waitTime = 10;

    @Override
    public void customize(Connector connector) {
        this.connector = connector;
    }

    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        connector.pause();
        var executor = connector.getProtocolHandler().getExecutor();
        if (executor instanceof ThreadPoolExecutor) {
            ThreadPoolExecutor threadPool = (ThreadPoolExecutor) executor;
            threadPool.shutdown();
            try {
                if (!threadPool.awaitTermination(waitTime, TimeUnit.SECONDS)) {
                    System.out.println("Please try forceful shutdown");
                }
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

Data backup with @PreDestroy

Using the @PreDestroy annotation on a bean method allows execution of backup logic just before the Spring container shuts down.

package com.ymy.config;

import org.springframework.context.annotation.Configuration;
import javax.annotation.PreDestroy;

@Configuration
public class DataBackupConfig {
    @PreDestroy
    public void backData() {
        System.out.println("Backing up data......");
    }
}
Spring Boot project started
Spring Boot project started
Process ID list
Process ID list
Log after kill -15
Log after kill -15
Error after interruption
Error after interruption
Actuator shutdown response
Actuator shutdown response
Actuator shutdown log
Actuator shutdown log
Graceful shutdown log
Graceful shutdown log
Backup log output
Backup log output
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.

Javaspring-bootTomcatGraceful ShutdownActuatorPreDestroyLinux kill
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

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.