Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

  • Java并发

  • Java IO

  • JVM

    • JVM概述
    • JVM基础

    • 类加载机制

    • 运行时内存

    • 垃圾回收

    • 执行引擎与优化

      • 解释执行与JIT编译
        • 1. 解释执行
        • 2. JIT 编译
        • 3. 为什么不全部提前编译
        • 4. 分层编译
        • 5. 热点探测
        • 6. 反优化
        • 7. 阶段小结
        • 8. 分层编译流程图
        • 9. 为什么 Java 有预热
        • 10. 反优化示例
        • 专家速查表
        • 11. Tips 快问快答
      • 热点代码与编译优化
      • 逃逸分析与标量替换
      • 锁优化
      • 类数据共享CDS与启动优化
    • 工具与问题排查

    • 调优实践与面试

目录

解释执行与JIT编译

JVM 执行字节码主要依赖解释器和 JIT 编译器。解释器让程序快速启动,JIT 让热点代码跑得更快。

# 1. 解释执行

解释器逐条读取字节码并执行。

优点:

  • 启动快。
  • 实现简单。
  • 不需要等待编译。

缺点:

  • 长期运行性能不如本地机器码。

解释执行适合冷代码,也适合程序启动初期。

# 2. JIT 编译

JIT(Just-In-Time)即时编译会把热点字节码编译成本地机器码。

字节码 -> JIT编译 -> 机器码

机器码可以直接被 CPU 执行,性能更高。

# 3. 为什么不全部提前编译

全部提前编译会带来问题:

  • 启动变慢。
  • 编译不常执行的代码浪费资源。
  • 缺少运行时 profiling 信息。
  • 很多优化依赖运行时真实类型和分支概率。

JIT 的优势是可以根据运行时数据做优化。

# 4. 分层编译

HotSpot 使用分层编译思想。

常见编译器:

  • C1:编译快,优化较少,适合启动阶段。
  • C2:编译慢,优化强,适合热点代码。

分层编译让 JVM 在启动速度和峰值性能之间取得平衡。

# 5. 热点探测

JVM 会通过计数器识别热点代码:

  • 方法调用计数器。
  • 回边计数器。

方法被频繁调用,或者循环执行次数很多,就可能触发 JIT 编译。

# 6. 反优化

JIT 优化基于运行时假设。如果假设后来不成立,JVM 可能撤销已编译代码,回退到解释执行或重新编译。

例如:

  • 原本只有一个实现类,后来加载了新的子类。
  • 类型分布发生变化。
  • 内联假设失效。

这就是 JVM 动态优化的灵活性。

# 7. 阶段小结

解释执行保证启动速度,JIT 编译提升长期性能。现代 JVM 通过分层编译、热点探测和反优化,把运行时信息转化为性能收益。理解 JIT,是理解 Java 为什么能在长期运行后越来越快的关键。

# 8. 分层编译流程图

方法首次执行
  │
  ▼
解释器执行
  │
  ├─ 调用次数少
  │   └─ 继续解释执行
  │
  └─ 达到热点阈值
      ▼
    C1 编译(快,优化少)
      │
      ├─ 热度下降
      │   └─ 使用现有编译结果
      │
      └─ 持续热点
          ▼
        C2 编译(慢,优化强)
          │
          ▼
        执行优化后的机器码

解释器、C1、C2 不是互斥关系,而是共同组成分层执行体系。

# 9. 为什么 Java 有预热

Java 服务刚启动时,很多代码还在解释执行或低级别编译阶段。随着请求进入,热点路径被识别并编译优化,性能逐渐稳定。

启动初期:解释执行多,RT 较高
预热阶段:热点逐渐编译,RT 下降
稳定阶段:热点路径机器码执行,RT 稳定

这就是为什么压测 Java 服务时要有预热阶段。没有预热的压测数据会低估长期运行性能。

# 10. 反优化示例

假设接口只有一个实现:

interface PayService {
    void pay();
}

class AliPayService implements PayService {
    public void pay() {
    }
}

JIT 可能把接口调用优化成直接调用。后来动态加载了新的实现:

class WechatPayService implements PayService {
    public void pay() {
    }
}

原来的单实现假设不成立,JVM 可能反优化,回退后重新收集类型信息。

# 专家速查表

执行方式 优势 代价
解释执行 启动快、无需编译等待 长期运行性能较低
C1 编译 编译快、适合启动阶段 优化深度有限
C2 编译 优化强、峰值性能高 编译成本更高
分层编译 兼顾启动和峰值性能 行为更复杂
OSR 循环中途切到编译代码 分析时调用栈更复杂

JIT 优化依赖运行时画像。压测预热不足、代码路径变化、分支预测失效,都可能导致线上性能和本地测试差异明显。

# 11. Tips 快问快答

Q:为什么 Java 程序刚启动时慢一点?

A:热点代码还没充分 JIT 编译,类加载和框架初始化也在发生。

Q:JIT 编译后的机器码存在哪里?

A:通常存放在 Code Cache 中。

Q:解释执行是不是没用了?

A:不是。解释器让程序快速启动,也为 JIT 收集 profiling 信息。

Q:为什么微基准测试要用 JMH?

A:JMH 能处理预热、死代码消除、编译优化等问题,普通 main 方法很容易测错。

上次更新: 2026/06/25, 14:19:18
GC日志分析
热点代码与编译优化

← GC日志分析 热点代码与编译优化→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式