# 编译执行与解释执行的区别是什么?JVM 使用哪种方式?
7 min read
Table of Contents
编译执行与解释执行的区别是什么?JVM 使用哪种方式?
编译执行与解释执行的区别及 JVM 的执行方式
【核心定义】
编译执行是将源代码一次性翻译成目标机器码后执行,而解释执行是逐行读取源代码并实时翻译执行;JVM 采用“解释执行 + 即时编译(JIT)”的混合模式。
【关键要点】
-
编译执行(Compilation)
- 本质:一次性将整个源代码转换为目标平台(如 x86、ARM)的本地机器码,生成可执行文件
- 执行过程:编译阶段完成所有翻译工作,执行阶段直接运行机器码
- 典型代表:C/C++、Go、Rust
-
解释执行(Interpretation)
- 本质:逐行读取源代码,实时翻译并立即执行,不生成持久化的机器码文件
- 执行过程:翻译和执行交替进行,每次运行都需要重新解释
- 典型代表:早期 JavaScript、Python(默认)、PHP
-
JVM 的混合执行模式
- 解释器:快速启动,逐条解释字节码执行
- 即时编译器(JIT):运行时将热点代码编译为本地机器码
- 分层编译策略:结合解释器的快速响应和 JIT 的优化执行
【深度推导/细节】
性能对比的底层逻辑
编译执行优势:1. 编译期可进行深度优化(如循环展开、内联、死代码消除)2. 运行时无翻译开销,直接执行机器码3. 可进行跨过程优化(过程间分析)
解释执行优势:1. 无需等待编译完成,快速启动2. 平台无关性,解释器适配不同平台即可3. 支持动态特性(如 eval、反射)更灵活
JVM 的平衡策略:Step 1: 所有代码先由解释器执行 → 保证快速启动Step 2: 监控方法调用次数和循环回边次数Step 3: 识别热点代码(HotSpot 名称由来)Step 4: 触发 JIT 编译,生成优化后的本地代码Step 5: 后续调用直接执行本地代码JVM 的分层编译(Tiered Compilation)
- 第 0 层:解释执行,收集性能监控数据
- 第 1 层:C1 编译器(客户端编译器),快速编译,轻度优化
- 第 2 层:C2 编译器(服务端编译器),深度优化,耗时较长
- 第 3 层:C1 编译带完整性能监控
- 第 4 层:C2 编译,使用第 3 层收集的数据进行激进优化
【关联/对比】
与其他执行模型的对比
| 特性 | 纯编译执行 | 纯解释执行 | JVM 混合模式 |
|---|---|---|---|
| 启动速度 | 慢(需完整编译) | 快(直接解释) | 快(先解释) |
| 峰值性能 | 高(充分优化) | 低(解释开销) | 高(JIT优化) |
| 内存占用 | 低(仅机器码) | 高(源码+解释器) | 中(字节码+本地代码) |
| 平台移植 | 需重新编译 | 解释器移植即可 | 一次编译,到处运行 |
| 动态性支持 | 困难 | 容易 | 中等(通过反射) |
与 .NET CLR 的对比
- 相似点:都采用字节码中间格式和 JIT 编译
- 不同点:.NET 有 NGEN(预编译)机制,可提前编译为本地代码;JVM 更强调运行时自适应优化
『面试官追问』
可能追问的问题:
-
JVM 如何确定热点代码?
- 方法调用计数器:统计方法被调用的次数
- 回边计数器:统计循环体执行的次数
- 默认阈值:客户端模式 1500 次,服务端模式 10000 次
-
为什么不全量编译而是混合模式?
- 启动时间:全量编译导致启动缓慢
- 代码特性:部分代码只执行一次,编译不划算
- 优化信息:运行时才能获取真实执行路径和类型信息
-
AOT(Ahead-of-Time)编译与 JIT 的区别?
- AOT:运行前静态编译(如 GraalVM Native Image)
- JIT:运行时动态编译
- 权衡:AOT 启动快但优化保守,JIT 启动慢但优化激进
-
JVM 不同版本执行方式的变化?
- Java 1.0-1.3:纯解释执行
- Java 1.4:引入 HotSpot JIT 编译器
- Java 7:引入分层编译(Tiered Compilation)
- Java 9:AOT 编译实验性支持
- Java 17:Project Leyden(静态镜像)持续推进
直击痛点:关键数字与设计考量
- 编译阈值 1500/10000:基于统计学的平衡点,太少则过早编译浪费资源,太多则错过优化时机
- 代码缓存大小:默认 240MB,存储 JIT 生成的本地代码,影响可优化的代码量
- 分层编译的 5 个层级:精细化的性能监控与编译成本控制
【版本差异与演进】
- Java 1.0-1.3:解释执行为主,性能瓶颈明显
- Java 1.4:HotSpot JVM 成熟,引入客户端/服务端编译器
- Java 7:分层编译成为默认,平衡启动速度和峰值性能
- Java 9:引入实验性 AOT 编译(jaotc)
- Java 15+:Project Leyden 探索静态镜像,解决 Java 启动慢、内存占用高的问题
【总结升华】
JVM 的混合执行模式体现了工程上的精妙权衡:用解释器保证快速启动和平台无关性,用 JIT 编译器追求峰值性能,用分层策略平衡编译成本与收益。这种自适应优化机制让 Java 既能”一次编写,到处运行”,又能通过运行时优化获得接近原生代码的性能,这正是 JVM 二十多年持续演进的核心竞争力。