JIT(即时编译)

返回 Java 基础


解释执行 vs 编译执行

解释执行JIT 编译
方式逐行翻译字节码执行将热点字节码编译为机器码
启动速度慢(需要编译时间)
运行速度快(直接执行机器码)
内存占用较高(缓存编译后的机器码)

JVM 默认混合模式(Mixed Mode):启动阶段解释执行,热点代码触发 JIT 编译。


热点探测

JVM 通过计数器判断哪些代码是热点:

计数器触发对象阈值(默认)
方法调用计数器方法被调用次数Client 1500 / Server 10000
回边计数器循环体执行次数触发 OSR(栈上替换)

超过阈值 → 提交给 JIT 编译器异步编译 → 编译完成后替换为机器码。

OSR(On-Stack Replacement):方法执行过程中,直接将正在运行的解释版本替换为编译版本,无需等待方法返回。


编译器层级(分层编译)

JDK 8+ 默认开启分层编译(Tiered Compilation),共 5 层:

层级执行方式说明
0解释执行无性能数据收集
1C1 编译无 profiling,简单优化
2C1 编译带方法调用次数/回边计数
3C1 编译带完整 profiling(类型、分支等)
4C2 编译激进优化,基于 profiling 数据
启动 → 0层解释 → 3层C1(收集数据)→ 4层C2(激进优化)

C1 vs C2

C1(Client 编译器)C2(Server 编译器)
编译速度
优化程度中等激进
适用场景快速启动,短时运行长时间运行的服务端程序
典型优化内联、去虚化标量替换、锁消除、循环展开

主要优化技术

方法内联(Inlining)

将被调用方法的方法体直接嵌入调用处,消除方法调用开销,并为后续优化创造条件。

// 内联前
int add(int a, int b) { return a + b; }
int result = add(x, y);
 
// 内联后(概念)
int result = x + y;

内联条件:方法不超过 35 字节(-XX:MaxInlineSize)、调用频繁、非虚方法或可去虚化。

逃逸分析(Escape Analysis)

分析对象的作用域是否逃出当前方法/线程:

逃逸类型说明优化手段
无逃逸对象只在方法内使用栈上分配 / 标量替换
方法逃逸对象被外部方法引用部分优化
线程逃逸对象被其他线程引用无法优化

栈上分配:无逃逸对象直接分配在栈帧上,方法返回自动回收,减轻 GC 压力。

标量替换:将对象拆散为基本类型字段,直接存入寄存器,完全避免对象创建。

锁消除(Lock Elimination)

逃逸分析确认对象不会被多线程共享时,去掉多余的同步锁:

// StringBuffer 是线程安全的,但 sb 不逃逸,锁会被消除
public String concat(String a, String b) {
    StringBuffer sb = new StringBuffer();
    sb.append(a);
    sb.append(b);
    return sb.toString();
}

锁粗化(Lock Coarsening)

连续对同一对象加锁/解锁,合并为一次加锁,减少锁操作次数。

循环展开(Loop Unrolling)

减少循环判断次数,提高指令级并行度:

// 展开前:循环 100 次
// 展开后:每次迭代执行 4 个操作体,循环 25 次

去虚化(Devirtualization)

虚方法调用需要通过虚方法表查找,开销大。JIT 根据 profiling 数据,若某个调用点的接收者类型总是同一个类,则直接内联该类的实现(单态内联缓存)。


AOT(Ahead-of-Time)编译

与 JIT 相对,AOT 在运行前将代码编译为机器码:

JITAOT
编译时机运行时运行前
启动速度慢(需预热)
峰值性能高(可利用运行时数据)较低
代表HotSpot JITGraalVM Native Image

GraalVM Native Image 将 Java 程序编译为独立二进制,启动时间从秒级降至毫秒级,适合 Serverless / 容器场景。


常用 JVM 参数

-XX:+TieredCompilation          开启分层编译(JDK8+ 默认开启)
-XX:CompileThreshold=10000      触发 JIT 的方法调用阈值
-XX:+PrintCompilation           打印 JIT 编译日志
-XX:+DoEscapeAnalysis           开启逃逸分析(默认开启)
-XX:+EliminateLocks             开启锁消除(默认开启)
-XX:MaxInlineSize=35            内联方法的最大字节数

相关链接