什么是 AOT 编译?和 JIT 有什么区别?

#Java#面试八股

什么是 AOT 编译?和 JIT 有什么区别?

结论先行:**AOT(Ahead-Of-Time,提前编译)**是在程序运行之前就把字节码编译成本地机器码,产物是平台相关的可执行文件或共享库;JIT(Just-In-Time,即时编译)是在运行期间根据实际执行情况编译热点代码。两者的核心差别不在「编译」,而在有没有运行期画像:AOT 只能靠静态分析与预热构建期的 profile 猜测,JIT 能看到真实的类型分布与分支走向,因此 AOT 启动快、峰值性能通常略低。

一、对比

维度AOTJIT
编译时机构建期运行期(首次达到热点阈值后)
产物原生可执行文件 / 动态库内存中的机器码缓存
启动速度毫秒级,无预热秒级到数十秒,需要预热
峰值性能接近 JIT,缺少动态优化更高,可内联、去虚化、按 CPU 生成指令
内存占用低,无需 JIT 编译器与元空间代码缓存高,需 CodeCache、元空间、编译线程
动态性反射、动态代理、动态类加载需额外配置原生支持
典型实现GraalVM native-image、JDK 9 的 jaotc(已移除)HotSpot C1/C2、Graal JIT

二、时间轴上的位置

JIT:
  启动 ── 解释执行 ── 热点探测 ── C1 编译 ── C2 编译(峰值)
   │        ↑ 慢                    ↑ 快
   └─ 冷启动阶段,QPS 爬坡

AOT:
  构建期 ── 静态分析 + 可达性分析 ── 机器码 + 堆快照
  启动 ────────────────────────── 直接跑(毫秒级)

组合(CDS / AppCDS / Leyden):
  构建期存档类元数据 ── 启动直接映射 ── 仍由 JIT 接管热点

三、AOT 的典型用法

# GraalVM 原生镜像:构建期把可达的类全部编译进可执行文件
native-image \
  --no-fallback \
  -H:Name=order-service \
  -H:ReflectionConfigurationFiles=reflect-config.json \
  -H:IncludeResources='application.*\.yml' \
  -jar order-service.jar

# 启动后没有 JVM 预热:直接测 QPS
./order-service &
time curl -s http://127.0.0.1:8080/api/order/1 > /dev/null
reflect-config.json 片段(反射需要显式声明):
[
  { "name": "com.example.Order", "allDeclaredMethods": true },
  { "name": "com.example.OrderMapper", "methods": [ { "name": "selectById" } ] }
]

四、不换运行时的「半个 AOT」:CDS

如果不想换 GraalVM,可以用**类数据共享(CDS)**把类加载与验证的结果存档,减少启动期的解析与验证开销:

# 生成基线存档(JDK 12+ 默认自带 classes.jsa)
java -Xshare:dump -XX:SharedArchiveFile=app.jsa -cp app.jar

# 应用存档启动,观察启动耗时
java -Xshare:on -XX:SharedArchiveFile=app.jsa -cp app.jar com.example.Main

# 动态存档:先跑一段,再落盘
java -XX:ArchiveClassesAtExit=app.jsa -cp app.jar com.example.Main

五、常见追问

追问回答要点
AOT 一定更快吗启动快、内存小,但峰值通常不如 JIT,因为缺少运行期类型画像,虚方法只能保守处理
JDK 9 的 jaotc 呢实验特性,JDK 16 起废弃、JDK 17 移除,主流 AOT 方案是 GraalVM
AOT 为什么反射会失败构建期静态分析看不到反射目标,类被裁掉;需要 reflect-config、resource-config 显式声明
什么服务适合 AOTServerless、CLI、冷启动敏感的边缘服务;长驻的高吞吐服务用 JIT 更划算
AOT 与 JIT 会长期并存吗会,Project Leyden 的方向是「静态镜像 + 运行期优化」结合,让两者优势叠加

小结

AOT 把编译成本搬到构建期,换来快启动小内存;JIT 把编译留给运行期,换来更强的优化上限。选型看「冷启动是否在关键路径」和「能否接受构建期配置反射」,而不是谁的编译技术更先进。

笔记加载中…