AOT与JIT
AOT(Ahead-of-Time,预先编译)和 JIT(Just-In-Time,即时编译)是两种将高级语言代码转换为机器可执行指令的核心技术。
他们之间的核心区别在于,一种预先编译,一种在运行时解释。
对比
AOT
在程序发布前,编译器直接将源代码编译为特定平台的机器码。
运行时无需编译器环境,直接加载并执行二进制文件,无额外编译开销。
典型的案例比如 C/C++,Java目前生态上也支持可以通过GraalVM Native Image来实现。
这种实现方式启动快、性能高,但是缺点是跨平台性差一点。
JIT
程序先加载平台无关的中间代码(如 Java 字节码、JavaScript 字节码),以解释执行启动(保证快速启动)
运行时动态统计热点代码(频繁执行的代码块),并将其编译为机器码缓存,后续直接调用缓存的机器码,大幅提升性能。
典型的案例比如 JVM 系语言使用JVM的解释器在运行时解释class字节码,JavaScript Node/浏览器的解释器。
这种实现方式跨平台性好,但是缺点是性能差一点,启动时由于运行时解释器加载和JIT扫描预热,整体较慢。
如果要简单举例的话,AOT/JIT/非热点代码解释执行 他们三者之间的关系:
- AOT(提前编译)
提前把整本书翻译成中文,你直接读中文版。
- JIT(即时编译)
听几句发现你很喜欢这段,于是直接把整段翻译成中文给你,以后都读中文版。
- 解释执行(非热点代码)
你说一句英文,译员现场口头翻译一句,说完就忘。下次你再说同一句,译员再重新翻译一遍。
→ 慢、重复劳动、不生成永久文本。
总结
| 特性 | AOT (预先编译) | JIT (即时编译) |
|---|---|---|
| 编译时机 | 运行前(开发 / 打包阶段完成) | 运行时(程序启动后动态进行) |
| 核心比喻 | 完整中文版书籍 | 同声传译(对于经常听到的句段直接复用翻译好的) |
| 典型产物 | 独立可执行二进制文件(如 .exe、可执行脚本) |
平台无关字节码(如 .class、.js)+ 运行时编译器 |
| 代表技术 | C/C++/Rust/Go 编译器、GraalVM Native Image、.NET Native AOT | JVM HotSpot、V8 引擎、.NET CLR JIT |
JavaFX
我们上面提到了 Java本身应该是归在 JIT 这一部分的,并且 JDK17+ 开始可以通过 GraalVM Native Image 来实现 AOT 的打包编译方式,直接生成对应平台的可执行代码而不是原来的jar
但是 Java FX 这个又不太一样,由于是客户端渲染技术,JavaFX 默认使用的是 100% JIT,同时也可以在 Java17 & JavaFX17 后用 GraalVM 把 JavaFX 编写的客户端程序打成各个平台的执行文件版本。