You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何调试导致Helidon服务器突然关闭的SIGTERM问题

问题背景

简单Java程序收到kill -SIGTERM信号时,会触发JVM关闭钩子(Runtime.addShutdownHook()),钩子执行完成后JVM可正常退出。
简单Helidon服务器自带JVM关闭钩子,能保证CDI正常关闭、Netty停止监听,@BeforeDestroyed、@Destroyed注解逻辑和关闭钩子仅输出日志,最终服务器与JVM都能干净退出。

但我维护的一个复杂Helidon服务器出现异常:

  • 当通过监控特定删除文件触发关闭流程时,能看到Netty关闭、@BeforeDestroyed/@Destroyed执行、关闭钩子日志,服务器和JVM干净退出,耗时1.011秒。
  • 但发送kill -SIGTERM信号后,服务器瞬间退出(数毫秒内),Netty未关闭,上述关闭逻辑和钩子都未执行。
    该问题在Windows(使用Cygwin的kill命令)和Linux环境下均可复现。

调试方法
  • 显式注册信号处理器并打日志:通过Signal.handle(new Signal("TERM"), handler)注册自定义SIGTERM处理器,在处理器中输出详细日志,确认信号是否被接收、处理器执行是否被中断。
  • 检查JVM退出状态码:Linux下执行echo $?,Windows下查看进程退出码:143对应正常SIGTERM触发退出,非该值则可能是代码直接调用System.exit()导致的强制退出。
  • 启用JVM退出诊断日志:启动时添加JVM参数-XX:+PrintExitFlags、-XX:+PrintCommandLineFlags、-Xlog:exit*=debug,查看退出时的JVM状态标志,确认是正常关闭还是强制退出。
  • 排查自定义信号拦截逻辑:检查代码中是否有其他SIGTERM处理器,可能覆盖了Helidon默认钩子,或处理器内直接调用System.exit()跳过了关闭流程。
  • 对比线程快照:发送SIGTERM前几秒用jstack(Linux)/jstack.exe(Windows)获取线程dump,发送信号后立即再获取一次,对比线程状态,排查是否有线程死锁、阻塞或关键线程被意外终止。
  • 排查第三方依赖:检查项目是否引入JNI等原生库,这类库可能直接捕获SIGTERM并终止进程,导致JVM无法触发关闭钩子。

可能导致异常退出的情况
  • 自定义处理器直接退出:代码中注册的SIGTERM处理器内调用了System.exit(int),跳过JVM关闭钩子执行流程。
  • 原生代码拦截信号:依赖的JNI或原生组件捕获SIGTERM后直接终止进程,JVM无机会执行关闭逻辑。
  • JVM致命错误:收到信号时JVM正处理OOM、内存损坏等致命错误,直接触发紧急退出,跳过关闭钩子。
  • 关闭钩子被移除:代码中调用Runtime.removeShutdownHook()移除了Helidon默认的关闭钩子,导致信号触发后无对应逻辑执行。
  • 进程处于不可中断状态:进程因IO阻塞等原因处于操作系统不可中断状态,收到信号后被系统强制终止。

内容的提问来源于stack exchange,提问作者Nathan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:02:43