如何让JVM在SIGSEGV崩溃后快速退出?
问题描述
我们的一项服务因TensorFlow Java的问题频繁崩溃,这个情况我们能接受——毕竟K8s会重启实例,而且我们有足够多的实例支撑。但麻烦的是JVM要等好几分钟才会终止。有没有办法在原生代码触发SIGSEGV时强制让进程快速退出?
崩溃时的错误日志:
corrupted size vs. prev_size while consolidating # # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x00007fe4f321a898, pid=1, tid=545 # # JRE version: OpenJDK Runtime Environment Zulu21.28+85-CA (21.0+35) (build 21+35) # Java VM: OpenJDK 64-Bit Server VM Zulu21.28+85-CA (21+35, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64) # Problematic frame: # C [libc.so.6+0x28898] abort+0x178 # # Core dump will be written. Default location: /data/core # # An error report file with more information is saved as: # /data/hs_err_pid1.log
数分钟后出现的日志:
# [ timer expired, abort... ] [thread 1037 also had an error]
解决方法
- 禁用核心转储:JVM崩溃时生成核心转储是耗时的主要原因之一,启动服务前执行
ulimit -c 0,或在K8s Pod配置中添加环境变量ULIMIT="-c 0",直接跳过核心转储生成。 - JVM参数调优:在Java启动命令中加入以下参数,减少崩溃后的资源消耗和等待时间:
-XX:OnError="kill -9 %p":触发致命错误时立即用SIGKILL终止进程-XX:ErrorFile=/dev/null:禁止生成错误日志文件-XX:+DisableAttachMechanism:禁用JVM附加机制,简化崩溃流程
示例命令:java -XX:OnError="kill -9 %p" -XX:ErrorFile=/dev/null -jar your-service.jar
- 自定义信号处理库:编写C语言共享库,为SIGSEGV注册直接终止进程的处理逻辑:
编译:#include <signal.h> #include <unistd.h> void handle_sigsegv(int sig) { _exit(1); // 直接终止,不执行JVM清理 } __attribute__((constructor)) void setup_signal_handler() { struct sigaction sa; sa.sa_handler = handle_sigsegv; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGSEGV, &sa, NULL); }gcc -shared -fPIC -o libfastexit.so fastexit.c,启动时加载:LD_PRELOAD=./libfastexit.so java -jar your-service.jar - K8s健康检查兜底:配置
livenessProbe,检测服务可用性,失败后立即重启Pod:livenessProbe: exec: command: ["curl", "http://localhost:your-port/health"] initialDelaySeconds: 30 periodSeconds: 10 failureThreshold: 2
内容的提问来源于stack exchange,提问作者David Tinker
相关产品推荐
相关产品推荐

