OpenJDK默认采用分层编译:第0层解释执行(采集热点数据)、第1–3层C1轻量优化、第4层C2激进优化;-Xint强制纯解释,无优化、性能极差;-Xcomp强制首次调用前编译,启动慢、CodeCache易满。

OpenJDK 默认不是纯解释执行,也不是全程即时编译——它用的是分层编译(Tiered Compilation),解释执行和 JIT 编译共存,各司其职。
-Xint 强制解释执行时会发生什么
- JVM 完全跳过所有编译器,所有字节码都由解释器逐行翻译执行;
- 启动快、内存占用低,但性能极差:没有热点识别、无内联、无逃逸分析、无任何优化;
- 常见于调试或极端受限环境(如嵌入式模拟器),生产环境几乎不用;
- 用
java -Xint -version可验证是否进入纯解释模式(输出含interpreted mode); - 所有方法调用、循环、异常处理都走最慢路径,
System.nanoTime()都可能被反复解释多次。
-Xcomp 强制编译执行的代价
- JVM 尝试对每个方法首次调用前就编译,跳过解释阶段;
- 启动变慢(尤其类多、依赖重的应用),CodeCache 占用飙升;
- 编译压力大,容易触发
CodeCache is full警告甚至退化为解释执行; - 某些动态特性(如反射调用、Lambda 形成的类)可能无法及时编译,反而回退到解释器;
- 不推荐全局启用,仅适合极小、确定无反射/动态代理的脚本类场景。
分层编译(默认行为)怎么分配工作
- 第 0 层:纯解释执行(
Interpreter),负责快速启动和收集热点数据; - 第 1–3 层:C1 编译器(Client Compiler)介入,做轻量级优化(如方法内联、空检查消除),生成较短机器码;
- 第 4 层:C2 编译器(Server Compiler)接管,做激进优化(如循环展开、向量化、类型推测),但编译耗时长、内存开销大;
- 热点探测靠两个计数器:
MethodEntryCounter和BackEdgeCounter,阈值默认是 10000(可调-XX:CompileThreshold); - 若 C2 编译失败或类型假设被打破(比如新类加载导致继承链变化),会触发
deoptimization,临时切回解释执行。
真正容易被忽略的是:解释器不只是“慢的备胎”,它是 JIT 的数据采集器和安全兜底机制。没有它,JIT 就不知道该编谁、信谁、何时退;而过度依赖 JIT(比如关掉解释器或强行预编译),反而会让 Java 失去动态适应能力。


















