执行KILL PID执行钩子方法ShutdownHook

要触发代码中的 ShutdownHook(关闭钩子),需要让进程优雅退出(而非被强制终止)。Linux 系统中,可通过发送可被进程捕获的终止信号(如 SIGTERM)或让进程主动退出(如执行 System.exit())来实现。以下是具体处理方式:

一、通过系统信号触发(推荐)

发送非强制终止信号(如 SIGTERM,默认的 kill 信号),进程会捕获信号并执行 ShutdownHook 后退出。

1. 常用信号(可触发 ShutdownHook)
信号命令信号值含义适用场景
kill <PID>15优雅终止(默认信号)正常停止进程,触发收尾逻辑
kill -15 <PID>15同 kill <PID>显式指定优雅终止信号
kill -2 <PID>2中断信号(类似 Ctrl+C)模拟用户在终端按下 Ctrl+C
kill -1 <PID>1挂起信号(SIGHUP)通常用于让进程重新加载配置(部分程序会触发退出)
2. 操作示例

假设 Java 进程的 PID 是 12345

bash

# 方式 1:发送默认的 SIGTERM 信号(推荐)
kill 12345

# 方式 2:显式发送 SIGTERM 信号(与方式 1 等价)
kill -15 12345

# 方式 3:发送 SIGINT 信号(模拟 Ctrl+C)
kill -2 12345

执行后,进程会先执行 ShutdownHook 中的逻辑(如关闭资源、打印日志),然后正常退出。

二、通过进程主动退出触发

在代码中主动调用退出方法(如 System.exit(0)),JVM 会在退出前自动执行所有注册的 ShutdownHook

1. 代码中主动触发

java

运行

public class ShutdownHookTest {
    public static void main(String[] args) {
        // 注册 ShutdownHook
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("ShutdownHook 执行:释放资源中...");
        }));

        // 模拟业务逻辑执行一段时间后主动退出
        new Thread(() -> {
            try {
                Thread.sleep(5000); // 5秒后退出
                System.out.println("业务执行完毕,准备退出...");
                System.exit(0); // 主动调用 exit,触发 ShutdownHook
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

运行后,5 秒后进程会主动执行 System.exit(0),此时 ShutdownHook 会被触发。

2. 外部触发进程主动退出(如通过接口)

在服务中暴露一个 “优雅关闭” 接口,调用接口时执行 System.exit(0),适用于需要远程触发关闭的场景(如微服务的优雅下线):

java

运行

@RestController
public class ShutdownController {
    @PostMapping("/shutdown")
    public String shutdown() {
        // 异步执行退出,避免接口超时
        new Thread(() -> {
            try {
                Thread.sleep(1000); // 预留时间返回响应
                System.exit(0); // 触发 ShutdownHook 后退出
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        return "服务将优雅关闭";
    }
}

调用 POST /shutdown 接口后,服务会执行 ShutdownHook 并退出。

三、关键注意事项

  1. ShutdownHook 执行时间有限系统信号(如 SIGTERM)触发退出时,操作系统会等待进程一段时间(通常几秒到几十秒),若 ShutdownHook 执行过久(如卡住),系统可能会强制终止进程。因此,ShutdownHook 应只包含轻量的收尾逻辑(如关闭连接、保存缓存,避免复杂操作)。

  2. 避免在 ShutdownHook 中调用 System.exit()否则可能导致死锁或无限循环(ShutdownHook 调用 exit 会再次触发 ShutdownHook)。

  3. 多 ShutdownHook 的执行顺序不确定JVM 不保证多个注册的 ShutdownHook 线程的执行顺序,若有依赖关系,需手动协调(如用同步锁)。

  4. 容器环境中的特殊处理在 Docker、K8s 等容器中,容器停止时默认发送 SIGTERM 信号,等待一段时间(如 30 秒)后若进程未退出,会发送 SIGKILL 强制终止。因此,需确保 ShutdownHook 在容器的 “优雅停止超时时间” 内执行完毕(可通过 terminationGracePeriodSeconds 配置超时时间)。

总结

要触发 ShutdownHook,核心是让进程优雅退出

  • 优先使用 kill <PID>(或 kill -15 <PID>)发送 SIGTERM 信号;
  • 或在代码中主动调用 System.exit(0)(如通过接口触发)。

避免使用 kill -9SIGKILL),它会直接终止进程,无法触发任何收尾逻辑。

kill <PID>(默认发送 SIGTERM 信号)会触发 JVM 执行所有已注册的 ShutdownHook(关闭钩子)方法,直到所有钩子执行完成(或超时)后,进程才会退出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值