CodeWalk

JIT编译器(C1/C2/Graal)的工作原理

作者:古法程序员 · 2026-05-30 12:55

分析Java JIT(Just-In-Time)编译器的架构,包括C1(Client编译器)和C2(Server编译器)的区别、分层编译策略、热点代码识别方法以及Graal JIT编译器的特点。

回答

古法程序员

1. JIT编译器概述

  • javac将Java源码编译为.class字节码
  • JVM运行时,JIT将热点字节码编译为本地机器码
  • 混合模式:解释执行 + JIT编译

2. C1编译器(Client Compiler)

  • 使用-client参数(JDK 8)/ 分层编译第一层
  • 特点:编译速度快,但优化程度低
  • 适用于桌面应用、短生命周期应用

3. C2编译器(Server Compiler)

  • 使用-server参数(JDK 8)/ 分层编译第四层
  • 特点:编译速度慢(重量级),但优化深度极高
  • 优化技术:
    • 逃逸分析 → 栈上分配/标量替换/同步消除
    • 内联:方法调用替换为方法体(最大325字节,-XX:MaxInlineSize)
    • 循环优化:循环展开/循环剥离/循环向量化
    • 死代码消除:移除不可能执行的代码
    • 锁优化:锁消除/锁粗化
    • 窥孔优化:局部指令替换(如移位替代乘法)

4. 分层编译(Tiered Compilation,JDK 7+默认) | 层级 | 说明 | |------|------| | 0 | 解释执行 | | 1 | C1简单编译(无profiling) | | 2 | C1带profiling(方法调用和分支统计) | | 3 | C1完全profiling | | 4 | C2编译(基于profiling数据优化) |

5. 热点识别(Hot Spot Detection)

  • 基于计数器:方法调用计数器(-XX:CompileThreshold)+ 回边计数器(循环触发的编译)
  • 触发阈值:
    • C1:1500~10000(分层编译)
    • C2:10000(JDK 8默认)

6. Graal JIT(JDK 16+实验性)

  • 用Java编写的JIT编译器
  • 特点:更激进的优化、更好的内联决策、支持AOT(SubstrateVM)
  • 启用:-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler