OpenJDK JVM触发SIGSEGV崩溃,程序每周终止求助分析
分析OpenJDK 8下Netty PooledUnsafeDirectByteBuf引发的SIGSEGV崩溃问题
问题背景
服务器每周会因SIGSEGV信号触发程序挂起终止,系统资源充足无异常,升级OpenJDK 8版本后问题仍未解决。崩溃发生在Redisson的Netty线程中,错误指向Netty的PooledUnsafeDirectByteBuf.newInstance方法。
关键错误日志信息
# # SIGSEGV (0xb) at pc=0x0000fffeef35c9a4, pid=2369121, tid=0x0000fffc969ff1c0 # # JRE version: OpenJDK Runtime Environment (8.0_242-b08) (build 1.8.0_242-b08) # Java VM: OpenJDK 64-Bit Server VM (25.242-b08 mixed mode linux-aarch64 compressed oops) # Problematic frame: # j io.netty.buffer.PooledUnsafeDirectByteBuf.newInstance(I)Lio/netty/buffer/PooledUnsafeDirectByteBuf;+6 # # Core dump written. Default location: /home/hd/hd-bpm-cloud-server/core or core.2369121 # --------------- T H R E A D --------------- Current thread (0x0000fffe60003000): JavaThread "redisson-netty-17-11" [_thread_in_Java, id=2369414, stack(0x0000fffc96800000,0x0000fffc96a00000)] siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x00000008bbea5f6b
核心异常点:
- SIGSEGV错误类型为
SEGV_MAPERR,表示程序尝试访问未被映射到进程地址空间的内存 - 崩溃发生在
io.netty.buffer.PooledUnsafeDirectByteBuf.newInstance方法的第6行 - 线程为Redisson的Netty工作线程,JVM运行在aarch64架构,启用了压缩指针(compressed oops)
根本原因分析
结合Netty内存池机制和错误特征,可能的原因包括:
- Netty内存池并发bug:特定版本的Netty在aarch64架构下,多线程操作池化直接缓冲区时存在并发逻辑漏洞,导致内存地址访问非法。
PooledUnsafeDirectByteBuf依赖Unsafe API直接操作内存,并发场景下的竞态条件容易触发内存访问错误。 - 直接内存生命周期管理异常:直接内存由JVM和操作系统协同管理,如果Netty内存池在复用已被操作系统释放的DirectByteBuf内存块时,未正确校验内存有效性,会触发SIGSEGV。
- aarch64架构兼容性问题:OpenJDK 8u242在aarch64平台的Unsafe实现或压缩指针机制可能存在bug,导致Netty调用Unsafe API时出现内存地址计算错误。
- Redisson与Netty版本不兼容:Redisson对依赖的Netty版本有严格要求,版本不匹配可能导致内存池操作逻辑冲突,引发非法内存访问。
排查与修复建议
- 升级Netty与Redisson版本:将Netty升级到4.1.x系列的最新稳定补丁版(如4.1.94.Final及以上),同时同步升级Redisson到对应兼容的最新稳定版,多数内存池相关的架构兼容bug已在后续版本中修复。
- 临时禁用Unsafe内存池:通过JVM参数
-Dio.netty.noUnsafe=true强制Netty使用基于堆的缓冲区,或-Dio.netty.buffer.type=heap切换内存类型,验证问题是否消失,以此确认是否为直接内存池的问题。 - 分析Core Dump:使用GDB加载Core Dump文件和JDK调试符号,执行
bt查看完整栈回溯,info registers检查寄存器状态,定位具体的内存访问错误点:gdb $JAVA_HOME/bin/java core.2369121 bt info registers - 调整JVM参数:临时关闭压缩指针(
-XX:-UseCompressedOops)测试是否为压缩指针导致的地址计算错误;合理设置-XX:MaxDirectMemorySize,避免直接内存频繁回收引发的异常。 - 开启Netty内存池调试日志:将Netty日志级别设置为DEBUG,重点关注
io.netty.buffer.PoolArena、io.netty.buffer.PoolChunk相关日志,排查崩溃前的内存分配、回收操作是否存在异常。
内容的提问来源于stack exchange,提问作者kernelsky
相关产品推荐
相关产品推荐

