Apple Silicon Mac 上 JDK 8 报 CodeCache is full. Compiler has been disabled(used 才 24MB 也报满的排查与解决)

发布时间:2026/8/20 11:41:02
Apple Silicon Mac 上 JDK 8 报 CodeCache is full. Compiler has been disabled(used 才 24MB 也报满的排查与解决) 一、问题现象MacApple SiliconmacOS 26.x上用 IDEA 启动 Spring Cloud 微服务JeecgBoot 体系Spring Boot 2.7.18控制台打印INFO: Sentinel log output type is: file INFO: Sentinel log charset is: utf-8 INFO: Sentinel log base directory is: /Users/sun/logs/csp/ INFO: Sentinel log name use pid is: false INFO: Sentinel log level is: INFO CodeCache: size262144Kb used24029Kb max_used24029Kb free238114Kb bounds [0x000000010af50000, 0x000000010c6d0000, 0x000000011af50000] total_blobs13079 nmethods12292 adapters701 compilation: disabled (not enough contiguous free space left) OpenJDK 64-Bit Server VM warning: CodeCache is full. Compiler has been disabled. OpenJDK 64-Bit Server VM warning: Try increasing the code cache size using -XX:ReservedCodeCacheSize关键疑点size256MBused 才 24MBfree 还有 238MBJVM 却说CodeCache 满了、没有足够的连续空闲空间直接把 JIT 编译器关了。一开始以为是缓存不够把-XX:ReservedCodeCacheSize从 128m 调到 256m又加了-XX:UseCodeCacheFlushing重启后照样报。而且三个服务Gateway / System / 业务模块全都这样。二、排查过程1. 确认警告的数字矛盾第一反应free238114Kb却说没有连续空间这说明不是容量不足而是 CodeCache 扩展段segment分配失败——HotSpot 的代码缓存是按段扩展的初始提交一小块后面不够了再申请新段。这里的问题是新段申请不到可执行内存跟总大小没关系。2. 确认 JIT 是不是真的停了用 JDK 8 自带的 jstat 连续采样jstat-compilerpid# 采样 1Compiled Failed Invalid Time12592101.44# 间隔几秒采样 2还给服务打了流量Compiled Failed Invalid Time12592101.44Compiled 计数完全冻结打流量也不涨——JIT 编译器确实已被禁用整个服务退回纯解释执行性能只有正常水平的零头。这就是服务还能跑但越用越慢的典型状态。再看一眼 IDEA 默认塞的启动参数jps -lv-XX:ReservedCodeCacheSize256m -XX:UseCodeCacheFlushing -XX:TieredStopAtLevel1 -Xverify:noneTieredStopAtLevel1只用 C1 编译器也在场说明不是 C2 编译爆缓存这种常规剧情。3. 圈定环境uname-m# arm64Apple Siliconsw_vers# macOS 26.x/usr/libexec/java_home-V# 机器上装了 Corretto 8 (1.8.0_502 arm64) 和 Corretto 25jcmdpidVM.version# OpenJDK 25.502-b07 / JDK 8.0_502 —— 服务实际跑在 Corretto 8 上注意系统默认 JDK 是 25但 IDEA 项目 SDK 用的是Corretto 8 的 arm64 版。4. 反证同一台机器上IDEA 自己内置 JBRJDK 21——不报VSCode 的 Java 语言服务Corretto 25——不报只有跑在ARM64 版 JDK 8上的进程全灭三、原因这是 ARM64 (aarch64) 移植版 JDK 8 在新版 macOS15 Sequoia 之后上的已知兼容性问题JDK 8 的 aarch64 端口年代久远2021 年才合入主线且很快就进入维护期它申请可执行内存页W^X 模式的双映射的方式与新版 macOS 更严格的内存策略不兼容具体表现代码缓存初始段提交成功约 20MB 出头后续扩展段映射失败JVM 误判为CodeCache 满、无连续空间触发保护逻辑把 JIT 编译器禁用Oracle 官方论坛有同款案例ARM JDK 8 (8u431) 在 macOS 15 上used9973Kb、缓存基本全空同样报CodeCache is full. Compiler has been disabled所以-XX:ReservedCodeCacheSize调到多大都没用——预留地址空间再大第二段开始就提交失败。一句话不是你的参数不对是 JDK 8 的 ARM 版在新 macOS 上坏了。x86_64 的 Mac 或 Linux/Windows 上同样的 JDK 8 不会有这个问题。四、解决思路方案一推荐本地开发换 JDK 17arm64 原生版生产部署不动继续 JDK 8只是本机跑服务的 SDK 换成 JDK 17装 Temurin 17 (mac arm64)IDEAFile → Project Structure → Project SDK 换 17各服务 Run Configuration 的 SDK 同步换工程编译目标不用改Spring Boot 2.7.18 官方支持 JDK 17 运行时java.version1.8/java.version编译目标可保留也可以直接升到 17重启服务警告消失jstat -compiler的 Compiled 恢复增长。注意点Lombok 需要 ≥ 1.18.24JeecgBoot 2.7 年代的版本基本都满足个别老工具如旧版 Arthas在 17 上 attach 可能要加--add-opens java.baseALL-UNNAMED遇到再处理。方案二备选换 x86_64 版的 JDK 8 走 Rosetta如果工程依赖死活不兼容 17比如依赖了 sun.misc 内部 API、老字节码增强工具可以装x86_64 版的 Corretto 8IDEA 里给这个 SDK 强制指定 Rosetta 运行。能绕开 ARM 端口的 bug但 Rosetta 转译执行性能打折不推荐长期用。不行的方案都试过了-XX:ReservedCodeCacheSize256m/512m无效问题不在大小-XX:UseCodeCodeFlushing无效本来就不是缓存占满-XX:-TieredCompilation/TieredStopAtLevel1无效C1/C2 都一样栽在段分配上。五、结论项结论现象CodeCache used 24MB共 256MB即报 “CodeCache is full. Compiler has been disabled”根因ARM64 版 JDK 8 在 macOS 15 上代码缓存扩展段申请可执行内存失败JIT 被禁用影响服务不死但退化为纯解释执行性能骤降 5~10 倍判定手段看日志数字矛盾free 很大仍报满jstat -compilerCompiled 冻结解决本地换 JDK 17arm64 原生或 x86_64 JDK 8 Rosetta 兜底生产 JDK 8 不受影响一句话总结MacM 系列芯片 新版 macOS 上跑 JDK 8 出现这个警告别再调 ReservedCodeCacheSize 了——那是 ARM 版 JDK 8 的兼容性 bug本地开发换 JDK 17 才是正解。