jit编译代码存于堆外code cache,监控核心是largest_free_block(85%预警)和failed列(每分钟>50次表明编译被拒),需jstat -codecache与jstat -compiler联合轮询。

Java 中 JIT 编译后的代码存放在 Code Cache(代码缓存)区域,属于 JVM 的本地内存(堆外内存),由 JVM 管理但不归 GC 控制。监控其占用空间,核心是观察 已用大小、剩余最大连续块、编译失败次数 这三类指标,而非简单看“用了多少 MB”。
以下是最直接、可落地的监控方式:
一、用 jstat -codecache 实时查看 Code Cache 使用状态
这是最常用、零侵入、生产环境首选命令:
jstat -codecache <pid> [interval] [count]</pid>
关键字段含义:
- Used:当前已使用的 Code Cache 容量(KB/MB)
-
Max:Code Cache 最大容量(即
-XX:ReservedCodeCacheSize设置值) - Total:当前分配的总大小(可能小于 Max,尤其在未充分预热时)
- largest_free_block:最关键指标——最大连续空闲块大小(KB)。若持续低于 512 KB,即使 Used/Max 只有 70%,JIT 也大概率无法分配新空间,导致热点方法退回到解释执行
✅ 建议:每 10 秒轮询一次,
largest_free_block (即 1MB)立即告警;<code>Used / Max > 0.85且largest_free_block持续萎缩,说明碎片严重或容量不足。
二、配合 jstat -compiler 判断是否因 Code Cache 触发编译失败
jstat -compiler <pid></pid>
重点关注:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- Failed 列:表示 JIT 放弃编译的次数。每分钟增长超 30~50 次,极大概率是 Code Cache 不足或碎片化导致编译请求被拒
-
Compiled:成功编译的方法数,若长期停滞不涨,而
Failed持续上升,说明 JIT 已“半瘫痪”
⚠️ 注意:
Failed不仅由 Code Cache 引起,也可能是类型不稳定触发去优化,但两者常并发出现。建议两个命令联合看。
三、用 NMT(Native Memory Tracking)定位 Code Cache 实际内存开销
当需确认 Code Cache 是否真的占满、或排查是否与其他堆外内存(如 Direct Buffer、Metaspace)争抢时:
# 启动时加参数(必须启动时启用) -XX:NativeMemoryTracking=detail # 运行中查 Code Cache 占用 jcmd <pid> VM.native_memory summary scale=MB # 或更细粒度 jcmd <pid> VM.native_memory detail | grep -A 10 "Code Cache"</pid></pid>
输出中会明确列出:
- Code Cache (reserved=393216KB, committed=289536KB)
其中 committed 是实际已提交(即真正占用物理内存)的部分,比 jstat 的 Used 更贴近真实压力。
四、避免误判:区分“Code Cache 耗尽”和“编译器资源瓶颈”
-
jstat -codecache显示Used接近Max→ 容量硬不足,需调大-XX:ReservedCodeCacheSize(如 JDK 11+ 推荐 384m~512m) -
Used中等但largest_free_block极小 → 内存碎片化,需检查是否频繁加载/卸载类、动态代理泛滥、接口实现过多(破坏 JIT 单实现假设) -
Failed高 +largest_free_block正常 → 更可能是编译线程不足(-XX:CICompilerCount默认值偏低),或类型 profile 不稳定导致反复去优化
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










