即时编译与分层编译
了解 JVM 如何解释执行热点方法、随后对其进行即时编译,以及如何触发并观察编译过程
即时编译与分层编译 是 CoddyKit 上的免费 Java Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。
解释器与即时编译器
JVM 最初会解释执行字节码。当某个方法被频繁调用(变成“热点”)时,即时编译器会将其编译为本机机器码,从而大幅提升执行速度。
分层编译(Java 8 起的默认设置)
分层编译使用五个层级:T0(解释器)、T1(C1 简单编译)、T2(C1 有限分析)、T3(C1 完整分析)、T4(C2 完全优化)。方法变得越“热”,就会逐步提升到更高层级。
// Enable/disable tiered compilation:
// -XX:+TieredCompilation (default ON in Java 8+)
// -XX:-TieredCompilation (disables — only C2 used)C1 编译器(客户端编译器)
C1 编译速度快,并进行适度优化。它会添加分析指令,以便为 C2 测量调用频率和分支结果。
C2 编译器(服务端编译器)
C2(Opto)会执行深度优化:内联、逃逸分析、循环展开、向量化和死代码消除。它生成速度最快的本机代码,但编译所需时间更长。
// Force server JIT only:
java -server MyApp
// Or explicitly:
java -XX:-TieredCompilation MyApp // uses C2 only (warm-up is slower)热点阈值
方法在超过调用计数阈值后会进行即时编译。默认值:10,000 次调用(C2)。使用 -XX:CompileThreshold=N 进行调整。
// Lower threshold for faster warm-up (at cost of less optimization):
java -XX:CompileThreshold=1000 MyApp内联
内联是 C2 影响最大的优化:从热点代码中调用的小型方法会在调用位置被“复制粘贴”,从而消除方法分派开销,并支持进一步优化。
// Check inlining decisions:
java -XX:+PrintInlining -XX:+UnlockDiagnosticVMOptions MyApp
// Output:
// @ 5 com.example.User::getName (5 bytes) inlined逃逸分析
如果 C2 确定某个对象永远不会逃逸出当前方法(或线程),就可以将其分配在栈上而不是堆上,从而完全消除垃圾回收压力。
// Objects that don't escape are stack-allocated:
String result = new StringBuilder().append("Hello ").append(name).toString();
// The StringBuilder may be eliminated by escape analysis即时编译日志
使用 -XX:+PrintCompilation 记录每个方法的编译过程。输出会显示方法名称、层级和编译标志。
// java -XX:+PrintCompilation MyApp
// Output:
// 1 n java.lang.String::hashCode (0 bytes)
// 25 3 com.example.UserService::findById (42 bytes)
// 31 4 com.example.UserService::findById (42 bytes) made not entrant去优化
如果即时编译器的某个假设被破坏(例如加载了一个改变调用位置接收者类型的类),C2 就会执行“去优化”——退回到解释器或 C1。这是正常现象,通常对程序是透明的。
预热时间
即时编译需要时间。在生命周期很短的进程中,方法可能永远不会进行即时编译。可以使用提前编译(GraalVM Native Image),或使用类数据共享(CDS)缓存即时编译结果,以加快启动速度。
// Enable AppCDS to cache JIT-compilable classes:
java -XX:ArchiveClassesAtExit=app.jsa -cp app.jar MyApp # generate archive
java -XX:SharedArchiveFile=app.jsa -cp app.jar MyApp # use archiveGraalVM 即时编译器
GraalVM 使用以 Java 编写的即时编译器替代 C2。它支持更好的优化、为非 Java 语言使用即时编译器,并且是 Native Image(提前编译)的基础。
快速检查
哪种即时编译技术会将小型方法合并到调用方中,从而消除方法调用开销?
回顾
分层编译会将方法从 C1(快速编译、进行分析)逐步提升到 C2(深度优化)。关键优化包括:内联、逃逸分析和循环展开。使用 -XX:+PrintCompilation 观察即时编译器的决策。进行基准测试前请先预热。
常见问题解答
「即时编译与分层编译」课时是免费的吗?
是的 — 「即时编译与分层编译」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。
「即时编译与分层编译」这节课中我会学到什么?
了解 JVM 如何解释执行热点方法、随后对其进行即时编译,以及如何触发并观察编译过程 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Java Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「即时编译与分层编译」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Java Academy 课中编写并运行代码吗?
能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。