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

Tomcat随机崩溃报safepoint.cpp:687死锁错误求助

Tomcat随机崩溃(Safepoint死锁)排查与解决指南

一、先从近期配置变更入手排查

报错信息:Internal Error (safepoint.cpp:687), pid: xxx, tid: xxx
具体描述:Deadlock in safepoint code. Should have called back to the VM before blocking

  1. 回滚配置验证
    一周前的server.xml变更(端口调整、密钥库更新、shutdown指令修改)是最高优先级排查点:

    • 临时恢复shutdown指令为原默认值
    • 把80/8080端口Connector的redirectPort改回443,443端口Connector恢复原配置,AJP端口改回8009
    • 换回旧密钥库文件
      观察回滚后是否还会崩溃,若恢复正常,再逐一重新应用变更,定位具体触发项。
  2. 检查新密钥库兼容性
    新密钥库可能存在格式、算法或证书链问题,导致SSL线程异常阻塞:

    • 用keytool -list -v -keystore <新密钥库路径>查看密钥库信息,确认密钥算法(如RSA)、证书有效期、信任链是否完整
    • 对比旧密钥库配置,确保新密钥库使用的算法是JDK 8u181原生支持的(避免用JDK8后期才兼容的算法)

二、VM层面定位Safepoint死锁

  1. 分析hs_err文件
    从两个hs_err文件中重点提取:

    • 崩溃时处于阻塞状态的线程,尤其是http-nio-8443-exec-*、ajp-nio-8004-*这类和新端口相关的线程
    • 查看safepoint state部分,确认未到达安全点的线程及其调用栈
    • 排查是否有线程在执行JNI调用、Socket I/O阻塞时未正确释放VM锁
  2. 添加VM参数监控安全点行为
    在Tomcat启动脚本中加入以下参数,收集更详细的安全点日志:

    -XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1 -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime
    

    日志会输出安全点触发原因、停顿时间、未响应线程信息,帮你定位死锁根源。

三、不升级JDK的可行解决方案

  1. 调整Tomcat线程池配置
    若问题和SSL线程阻塞相关,调整Connector线程池参数降低阻塞概率:

    • 降低maxThreads,避免过多线程同时执行SSL握手或I/O操作
    • 增加connectionTimeout,减少线程因超时等待引发的异常
    • 启用asyncTimeout,及时清理异步请求的阻塞线程
  2. 切换到APR/OpenSSL实现
    放弃JVM默认的JSSE,改用Tomcat APR绑定的OpenSSL,将SSL处理移到Native层,减少JVM层面的安全点冲突:

    • 安装APR库和Tomcat Native组件
    • 在SSL Connector中配置protocol="org.apache.coyote.http11.Http11AprProtocol"
  3. 更换补丁版同版本JDK
    找第三方维护的JDK 8u181发行版(如Adoptium Temurin),这类版本通常会backport官方后期修复的安全点死锁补丁,无需升级大版本,避免兼容性问题。

四、其他排查方向

  • 检查系统资源:CPU、内存、文件句柄耗尽可能导致线程阻塞,进而触发安全点死锁
  • 排查JNI调用:如果应用用了JNI库,确认JNI代码是否规范,避免在JNI中长时间阻塞而未回调VM

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 20:47:14