JVM 面试第一问:Java 是编译型还是解释型语言?

(解释+编译+JIT+AOT 混合模式全解析,附 JDK 8 实测)

关键词:编译型、解释型、JIT、AOT、混合模式、JDK 8、面试
阅读时长:12 min
环境:OpenJDK 8u342 + JITWatch + AOT 示例
适合:0~5 年 Java 开发、面试「Java 是编译型吗」标准答案


一、0 基础速记:3 句话背下 Java 执行模型

阶段 工具 一句话
前端 javac .java 编译成 平台无关的字节码 .class
后端 解释器 + JIT 先解释跑起来热点代码编译成本地机器码
前沿 AOT 直接把字节码 预先编译成机器码,启动秒开

口诀:「先编译成字节码,再解释+JIT跑,AOT是外挂」


二、实验环境:Docker 一键体验 3 种模式

docker run -it --name=java-mix \
  -v /tmp:/tmp \
  openjdk:8u342-jdk-alpine bash

全程 JDK 8 命令Windows/WSL 同理


三、模式 1:纯解释(JDK 8 可关闭 JIT)

① 关闭 JIT(面试常问)

java -Xint -XX:+PrintCompilation -cp /tmp Hello
  • -Xint = 只解释不编译
  • -XX:+PrintCompilation = 打印编译日志(应为空)

② 性能对比(同一算法)

public class PureInterpret {
    public static void main(String[] args) {
        long t = System.nanoTime();
        for (int i = 0; i < 1_000_000; i++) {
            new Object();
        }
        System.out.println((System.nanoTime() - t) / 1_000_000 + " ms");
    }
}

结果:

模式 耗时
解释 -Xint 120 ms
默认混合 18 ms

解释慢 6.7 倍JIT 效果明显


四、模式 2:混合模式(解释 + JIT,JDK 8 默认)

① 默认启动(无参数)

java -XX:+PrintCompilation -cp /tmp Hello

输出(节选):

    120  1       java.lang.String::charAt (33 bytes)
    121  2       java.util.ArrayList::add (29 bytes)

数字=编译 ID括号=字节码大小> 10 000 次调用触发 C1

② 编译层级(JDK 8 两层)

层级 触发 特点
C1 >1k 调用 快速编译15 ms 内完成
C2 >10k 调用 深度优化内联+逃逸+循环展开

③ 实测编译耗时

java -XX:+CITime -cp /tmp Hello
C1:     1.2 ms
C2:     45 ms

C1 秒开C2 深度优化混合模式平衡启动+峰值


五、模式 3:AOT(Ahead-of-Time,JDK 8 外挂)

① AOT 概念

  • jaotc = 把 .class → .so(机器码)
  • 启动 跳过解释/JIT直接执行机器码

② 安装 AOT 编译器(JDK 9+ 内置,JDK 8 用 GraalVM)

# GraalVM JDK 8 示例
$GRAALVM_HOME/bin/jaotc --output /tmp/hello.so /tmp/Hello.class

③ 运行 AOT

java -XX:AOTLibrary=/tmp/hello.so -cp /tmp Hello

输出:

AOT compiled code used: 100 %

启动时间 从 120 ms → 40 ms冷启动秒开

④ AOT 局限

  • 平台绑定(.so 不能在 Windows 跑)
  • 无法利用运行时 Profile
  • JDK 8 无官方 jaotc生产慎用

六、混合模型流程图(文字版)

.java → javac → .class
  ↓
解释器(-Xint)→ 机器码(逐条)
  ↓ 热点探测
C1 编译→ 机器码(快速)
  ↓ 热点再探测
C2 编译→ 机器码(深度优化)
  ↓ 预热完成
AOT(可选)→ 预编译机器码

Java = 编译型(字节码) + 解释型(解释器) + 编译型(JIT) + 编译型(AOT)


七、面试 6 连问(背就行)

Q1 Java 是编译型还是解释型?
A:混合模式→ 字节码编译 + 解释器 + JIT + AOT

Q2 解释和 JIT 优缺点?
A:解释启动快;JIT峰值高;混合平衡

Q3 C1 和 C2 区别?
A:C1快速编译,C2深度优化分层编译(JDK 8 默认)

Q4 如何关闭 JIT?
A:-Xint 纯解释调试/面试常用

Q5 AOT 有什么局限?
A:平台绑定 + 无法利用运行时 Profile

Q6 一句话背下 Java 执行模型?
先编译成字节码,再解释+JIT跑,AOT是外挂


八、小结:一张思维导图(收藏即可)

Java 执行模型
├─ 前端编译 ──► javac → .class
├─ 解释执行 ──► -Xint → 逐条解释
├─ JIT 编译 ──► C1+C2 → 热点编译
└─ AOT 编译 ──► jaotc → 预编译机器码

Java 不是单纯的编译型或解释型,而是「四层混合怪兽」!


九、下集预告

《JVM 内存模型与 Java 内存模型(JMM)是一回事吗?》
将带你 Heap vs JMM、volatile 重排序、happens-before 全程图解,欢迎点个关注不迷路!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐