一、现象与告警
业务 Java 服务从 x86 迁移到鲲鹏 920 后,Prometheus 告警频繁触发:jvm_gc_pause_seconds_max 持续超过 500ms 阈值,部分请求超时率达到 2%。监控面板显示 GC 频率从每分钟 3 次升至每分钟 8 次,Full GC 间隔从 4 小时缩短至 40 分钟。
业务侧表现为:订单接口 P99 延迟从 50ms 飙升至 320ms,定时任务执行时间翻倍。初步排除内存泄漏(堆使用稳定在 4GB),问题集中在 GC 停顿时间过长。
二、环境信息
三、定位与排查
阶段一:GC 日志初步分析
开启 GC 详细日志,定位停顿发生的位置:
分析 GC 日志发现,停顿集中在 G1 Mixed GC 阶段,单次停顿 400-800ms。to-space exhausted 出现频率较高,说明存活对象复制效率低。
阶段二:JIT 编译热点分析
使用 jstat 观察 JIT 编译情况,发现鲲鹏上 JIT 编译耗时明显增加:
进一步用 perf 抓取热点函数:
发现 c2_CompilerThread 占用 15% CPU,且编译生成的机器码未充分利用 ARM NEON 指令。OpenJDK 11 的 JIT 编译器(C2)对 ARM64 的优化路径不完善,部分热点方法生成的代码效率低于 x86。
阶段三:毕昇 JDK 验证
毕昇 JDK(BiSheng JDK)是华为针对鲲鹏优化的 OpenJDK 发行版,内置 ARM 微架构感知的 JIT 优化。下载并替换验证:
四、解决方案与验证
第一步:切换毕昇 JDK 并调整 GC 参数
关键参数说明:
G1HeapRegionSize=8m:鲲鹏内存带宽较高,增大 Region 减少 Region 数量,降低管理开销 InitiatingHeapOccupancyPercent=35:提前触发并发标记,避免 Mixed GC 时存活对象过多 G1MixedGCCountTarget=16:增加 Mixed GC 轮次,分摊复制开销
第二步:NUMA 绑核启动
第三步:验证效果
使用 jstat 和 wrk 进行压测验证:
排查结论:
- JIT 编译器是主因:OpenJDK 11 的 C2 编译器对 ARM64 优化不足,热点方法生成的机器码效率低,导致 GC 期间对象复制缓慢。毕昇 JDK 内置鲲鹏微架构感知优化,编译产物效率显著提升。
- GC 参数需适配:x86 上的 GC 参数不能直接搬到鲲鹏,Region 大小和触发阈值需要根据 ARM64 内存特性重新调整。
- NUMA 影响不容忽视:Java 堆内存跨 NUMA 节点分配会增加 GC 扫描开销,绑核后 Full GC 间隔从 2.5h 延长至 5h。
生产建议:Java 服务迁移鲲鹏时,优先切换毕昝 JDK;GC 参数不要照搬 x86 配置,建议先用默认参数压测,再根据 GC 日志逐步调整;双路服务器务必配置 NUMA 绑核。
一、现象与告警
业务 Java 服务从 x86 迁移到鲲鹏 920 后,Prometheus 告警频繁触发:
jvm_gc_pause_seconds_max持续超过 500ms 阈值,部分请求超时率达到 2%。监控面板显示 GC 频率从每分钟 3 次升至每分钟 8 次,Full GC 间隔从 4 小时缩短至 40 分钟。业务侧表现为:订单接口 P99 延迟从 50ms 飙升至 320ms,定时任务执行时间翻倍。初步排除内存泄漏(堆使用稳定在 4GB),问题集中在 GC 停顿时间过长。
二、环境信息
三、定位与排查
阶段一:GC 日志初步分析
开启 GC 详细日志,定位停顿发生的位置:
分析 GC 日志发现,停顿集中在
G1 Mixed GC阶段,单次停顿 400-800ms。to-space exhausted出现频率较高,说明存活对象复制效率低。# 提取 GC 停顿超过 200ms 的记录 grep "Pause.*Mixed" /var/log/app/gc.log | grep -E "Pause.*[2-9][0-9]{2}\." | head -20阶段二:JIT 编译热点分析
使用
jstat观察 JIT 编译情况,发现鲲鹏上 JIT 编译耗时明显增加:进一步用
perf抓取热点函数:发现
c2_CompilerThread占用 15% CPU,且编译生成的机器码未充分利用 ARM NEON 指令。OpenJDK 11 的 JIT 编译器(C2)对 ARM64 的优化路径不完善,部分热点方法生成的代码效率低于 x86。阶段三:毕昇 JDK 验证
毕昇 JDK(BiSheng JDK)是华为针对鲲鹏优化的 OpenJDK 发行版,内置 ARM 微架构感知的 JIT 优化。下载并替换验证:
四、解决方案与验证
第一步:切换毕昇 JDK 并调整 GC 参数
# systemd service 文件修改 [Service] Environment="JAVA_HOME=/usr/local/bisheng-jdk-11.0.20" ExecStart=/usr/local/bisheng-jdk-11.0.20/bin/java \ -Xmx4g -Xms4g \ -XX:+UseG1GC \ -XX:MaxGCPauseMillis=200 \ -XX:G1HeapRegionSize=8m \ -XX:InitiatingHeapOccupancyPercent=35 \ -XX:G1MixedGCCountTarget=16 \ -XX:+UseStringDeduplication \ -XX:+ParallelRefProcEnabled \ -jar /opt/app/service.jar关键参数说明:
G1HeapRegionSize=8m:鲲鹏内存带宽较高,增大 Region 减少 Region 数量,降低管理开销InitiatingHeapOccupancyPercent=35:提前触发并发标记,避免 Mixed GC 时存活对象过多G1MixedGCCountTarget=16:增加 Mixed GC 轮次,分摊复制开销第二步:NUMA 绑核启动
# Java 进程绑定到 NUMA node 0,避免跨节点内存访问 numactl --cpunodebind=0 --membind=0 \ /usr/local/bisheng-jdk-11.0.20/bin/java \ -Xmx4g -Xms4g \ -XX:+UseG1GC \ -XX:MaxGCPauseMillis=200 \ -jar /opt/app/service.jar第三步:验证效果
使用
jstat和wrk进行压测验证:排查结论:
生产建议:Java 服务迁移鲲鹏时,优先切换毕昝 JDK;GC 参数不要照搬 x86 配置,建议先用默认参数压测,再根据 GC 日志逐步调整;双路服务器务必配置 NUMA 绑核。