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. 方法内联
        • 3. 去虚拟化
        • 4. 常量传播
        • 5. 死代码消除
        • 6. 循环优化
        • 7. 微基准测试注意点
        • 8. 阶段小结
        • 9. 热点探测数据结构
        • 10. 方法内联为什么重要
        • 11. 微基准错误示例
        • 专家速查表
        • 12. Tips 快问快答
      • 逃逸分析与标量替换
      • 锁优化
      • 类数据共享CDS与启动优化
    • 工具与问题排查

    • 调优实践与面试

目录

热点代码与编译优化

HotSpot JVM 的名字就来自热点代码优化。它不会平均对待所有代码,而是把编译和优化资源集中在最常执行的代码上。

# 1. 什么是热点代码

热点代码是运行中被频繁执行的代码。

常见形式:

  • 被频繁调用的方法。
  • 执行次数很多的循环体。
  • 高频业务路径。

JVM 会通过计数器和运行时 profiling 识别热点。

# 2. 方法内联

方法内联是最重要的 JIT 优化之一。

int result = add(a, b);

如果 add 足够简单,JIT 可能把方法体直接展开到调用点。

优点:

  • 减少方法调用开销。
  • 暴露更多优化机会。
  • 支持后续常量传播、死代码消除。

# 3. 去虚拟化

Java 方法调用通常支持多态。JIT 可以根据运行时类型信息,把虚方法调用优化为直接调用。

例如某接口实际只有一个实现类被频繁使用,JIT 可以基于这个假设优化调用。

如果后来加载了新的实现类,可能触发反优化。

# 4. 常量传播

如果某个值在运行时可以确定,JIT 可以把它传播到后续表达式中。

if (DEBUG) {
    log();
}

如果 DEBUG 恒为 false,相关代码可能被优化掉。

# 5. 死代码消除

不会影响结果的代码可能被消除。

int x = compute();
// x 没有被使用

如果 compute() 没有副作用,JIT 可能消除这段计算。

这也是写微基准测试时容易测错的原因:看起来在执行,实际可能被 JIT 优化掉。

# 6. 循环优化

JIT 会对循环做很多优化:

  • 循环展开。
  • 范围检查消除。
  • 循环不变量外提。
  • 向量化。

这些优化对数组处理、数值计算、高频循环很重要。

# 7. 微基准测试注意点

不要用普通 main 方法随手测性能。

原因:

  • JIT 预热不足。
  • 死代码被消除。
  • 常量折叠。
  • GC 干扰。
  • CPU 缓存影响。

Java 微基准测试应使用 JMH。

# 8. 阶段小结

JIT 优化的核心是利用运行时信息优化热点路径。方法内联、去虚拟化、常量传播、死代码消除和循环优化共同提升性能。理解这些优化,也能避免写出错误的性能测试。

# 9. 热点探测数据结构

JVM 会维护一些计数信息:

Method
├─ invocation counter   方法调用次数
├─ backedge counter     循环回边次数
└─ profiling data       类型分布、分支概率等

当计数超过阈值,方法或循环就可能进入编译队列。

# 10. 方法内联为什么重要

内联前:

caller()
  └─ call add()
       └─ return a + b

内联后:

caller()
  └─ 直接执行 a + b

内联带来的收益不只是少一次方法调用,更重要的是打开后续优化空间:

  • 常量传播。
  • 死代码消除。
  • 逃逸分析。
  • 锁消除。
  • 循环优化。

# 11. 微基准错误示例

错误写法:

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

问题:

  • 对象可能被消除。
  • 没有预热。
  • 循环可能被优化。
  • GC 和系统噪声没有控制。

正确方向是使用 JMH,并通过 Blackhole 消耗结果。

# 专家速查表

优化手段 作用 失效条件
方法内联 减少调用开销并扩大优化范围 方法过大、多态过强
逃逸分析 判断对象是否逃出作用域 对象被返回或共享
标量替换 拆散对象字段 逃逸分析失败
循环优化 降低循环成本 分支复杂或边界不稳定
去虚拟化 把虚调用变直接调用 类型分布变化

热点优化不是源码里写了某个模式就必然发生。JIT 会根据调用频率、类型分布、方法大小、逃逸情况和运行时反馈动态决定。

# 12. Tips 快问快答

Q:方法越小越容易内联吗?

A:通常是,但不是唯一条件。调用频率、字节码大小、类型稳定性等都会影响。

Q:为什么反射调用可能慢?

A:反射破坏部分静态类型信息,JIT 优化空间较小。现代 JDK 对反射也有优化,但普通直接调用仍更友好。

Q:JIT 会不会改变程序语义?

A:不会。JIT 优化必须保证在 Java 内存模型和语言语义下结果一致。

Q:热点代码是开发者手动标记的吗?

A:不是。JVM 根据运行时计数和 profiling 自动识别。

上次更新: 2026/06/25, 14:19:18
解释执行与JIT编译
逃逸分析与标量替换

← 解释执行与JIT编译 逃逸分析与标量替换→

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