)
一、問題現(xiàn)象MacApple SiliconmacOS 26.x上用 IDEA 啟動 Spring Cloud 微服務(wù)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關(guān)鍵疑點(diǎn)size256MBused 才 24MBfree 還有 238MBJVM 卻說CodeCache 滿了、沒有足夠的連續(xù)空閑空間直接把 JIT 編譯器關(guān)了。一開始以為是緩存不夠把-XX:ReservedCodeCacheSize從 128m 調(diào)到 256m又加了-XX:UseCodeCacheFlushing重啟后照樣報。而且三個服務(wù)Gateway / System / 業(yè)務(wù)模塊全都這樣。二、排查過程1. 確認(rèn)警告的數(shù)字矛盾第一反應(yīng)free238114Kb卻說沒有連續(xù)空間這說明不是容量不足而是 CodeCache 擴(kuò)展段segment分配失敗——HotSpot 的代碼緩存是按段擴(kuò)展的初始提交一小塊后面不夠了再申請新段。這里的問題是新段申請不到可執(zhí)行內(nèi)存跟總大小沒關(guān)系。2. 確認(rèn) JIT 是不是真的停了用 JDK 8 自帶的 jstat 連續(xù)采樣jstat-compilerpid# 采樣 1Compiled Failed Invalid Time12592101.44# 間隔幾秒采樣 2還給服務(wù)打了流量Compiled Failed Invalid Time12592101.44Compiled 計數(shù)完全凍結(jié)打流量也不漲——JIT 編譯器確實(shí)已被禁用整個服務(wù)退回純解釋執(zhí)行性能只有正常水平的零頭。這就是服務(wù)還能跑但越用越慢的典型狀態(tài)。再看一眼 IDEA 默認(rèn)塞的啟動參數(shù)jps -lv-XX:ReservedCodeCacheSize256m -XX:UseCodeCacheFlushing -XX:TieredStopAtLevel1 -Xverify:noneTieredStopAtLevel1只用 C1 編譯器也在場說明不是 C2 編譯爆緩存這種常規(guī)劇情。3. 圈定環(huán)境uname-m# arm64Apple Siliconsw_vers# macOS 26.x/usr/libexec/java_home-V# 機(jī)器上裝了 Corretto 8 (1.8.0_502 arm64) 和 Corretto 25jcmdpidVM.version# OpenJDK 25.502-b07 / JDK 8.0_502 —— 服務(wù)實(shí)際跑在 Corretto 8 上注意系統(tǒng)默認(rèn) JDK 是 25但 IDEA 項(xiàng)目 SDK 用的是Corretto 8 的 arm64 版。4. 反證同一臺機(jī)器上IDEA 自己內(nèi)置 JBRJDK 21——不報VSCode 的 Java 語言服務(wù)Corretto 25——不報只有跑在ARM64 版 JDK 8上的進(jìn)程全滅三、原因這是 ARM64 (aarch64) 移植版 JDK 8 在新版 macOS15 Sequoia 之后上的已知兼容性問題JDK 8 的 aarch64 端口年代久遠(yuǎn)2021 年才合入主線且很快就進(jìn)入維護(hù)期它申請可執(zhí)行內(nèi)存頁W^X 模式的雙映射的方式與新版 macOS 更嚴(yán)格的內(nèi)存策略不兼容具體表現(xiàn)代碼緩存初始段提交成功約 20MB 出頭后續(xù)擴(kuò)展段映射失敗JVM 誤判為CodeCache 滿、無連續(xù)空間觸發(fā)保護(hù)邏輯把 JIT 編譯器禁用Oracle 官方論壇有同款案例ARM JDK 8 (8u431) 在 macOS 15 上used9973Kb、緩存基本全空同樣報CodeCache is full. Compiler has been disabled所以-XX:ReservedCodeCacheSize調(diào)到多大都沒用——預(yù)留地址空間再大第二段開始就提交失敗。一句話不是你的參數(shù)不對是 JDK 8 的 ARM 版在新 macOS 上壞了。x86_64 的 Mac 或 Linux/Windows 上同樣的 JDK 8 不會有這個問題。四、解決思路方案一推薦本地開發(fā)換 JDK 17arm64 原生版生產(chǎn)部署不動繼續(xù) JDK 8只是本機(jī)跑服務(wù)的 SDK 換成 JDK 17裝 Temurin 17 (mac arm64)IDEAFile → Project Structure → Project SDK 換 17各服務(wù) Run Configuration 的 SDK 同步換工程編譯目標(biāo)不用改Spring Boot 2.7.18 官方支持 JDK 17 運(yùn)行時java.version1.8/java.version編譯目標(biāo)可保留也可以直接升到 17重啟服務(wù)警告消失jstat -compiler的 Compiled 恢復(fù)增長。注意點(diǎn)Lombok 需要 ≥ 1.18.24JeecgBoot 2.7 年代的版本基本都滿足個別老工具如舊版 Arthas在 17 上 attach 可能要加--add-opens java.baseALL-UNNAMED遇到再處理。方案二備選換 x86_64 版的 JDK 8 走 Rosetta如果工程依賴死活不兼容 17比如依賴了 sun.misc 內(nèi)部 API、老字節(jié)碼增強(qiáng)工具可以裝x86_64 版的 Corretto 8IDEA 里給這個 SDK 強(qiáng)制指定 Rosetta 運(yùn)行。能繞開 ARM 端口的 bug但 Rosetta 轉(zhuǎn)譯執(zhí)行性能打折不推薦長期用。不行的方案都試過了-XX:ReservedCodeCacheSize256m/512m無效問題不在大小-XX:UseCodeCodeFlushing無效本來就不是緩存占滿-XX:-TieredCompilation/TieredStopAtLevel1無效C1/C2 都一樣栽在段分配上。五、結(jié)論項(xiàng)結(jié)論現(xiàn)象CodeCache used 24MB共 256MB即報 “CodeCache is full. Compiler has been disabled”根因ARM64 版 JDK 8 在 macOS 15 上代碼緩存擴(kuò)展段申請可執(zhí)行內(nèi)存失敗JIT 被禁用影響服務(wù)不死但退化為純解釋執(zhí)行性能驟降 5~10 倍判定手段看日志數(shù)字矛盾free 很大仍報滿jstat -compilerCompiled 凍結(jié)解決本地?fù)Q JDK 17arm64 原生或 x86_64 JDK 8 Rosetta 兜底生產(chǎn) JDK 8 不受影響一句話總結(jié)MacM 系列芯片 新版 macOS 上跑 JDK 8 出現(xiàn)這個警告別再調(diào) ReservedCodeCacheSize 了——那是 ARM 版 JDK 8 的兼容性 bug本地開發(fā)換 JDK 17 才是正解。