Skip to content

第11章 后端编译与优化 - 代码指南

1. 代码结构

后端编译与优化相关代码位于 linsir-abc-core/src/main/java/com/linsir/abc/core/jvm/runtime/ 目录下,按照功能分为四个子包:

jvm/runtime/
├── jit/                          # JIT即时编译相关
│   ├── HotSpotDetector.java      # 热点代码探测演示
│   ├── JITAnalysisDemo.java      # JIT编译分析演示
│   └── TieredCompilationDemo.java # 分层编译演示
├── aot/                          # AOT提前编译相关
│   ├── AOTCompilationDemo.java   # AOT编译演示
│   └── AOTPerformanceTest.java   # AOT性能测试
├── optimization/                 # 编译器优化技术
│   ├── MethodInliningDemo.java   # 方法内联演示
│   ├── EscapeAnalysisDemo.java   # 逃逸分析演示
│   └── LoopOptimizationDemo.java # 循环优化演示
└── graal/                        # Graal编译器
    ├── GraalCompilerDemo.java    # Graal编译器演示
    └── GraalPerformanceTest.java # Graal性能测试

测试类位于 linsir-abc-core/src/test/java/com/linsir/abc/core/jvm/runtime/RuntimeCompilationTest.java

2. 代码作用

2.1 JIT编译相关 (jit包)

HotSpotDetector.java

  • 作用:演示JVM如何探测热点代码并触发JIT编译
  • 核心功能
    • hotMethod(): 热点方法演示,会被JIT编译器识别并编译
    • triggerOSR(): 触发OSR(栈上替换)编译,针对循环体热点
    • computeIntensive(): 计算密集型任务,展示JIT优化效果

JITAnalysisDemo.java

  • 作用:分析JIT编译过程和性能特点
  • 核心功能
    • 计算方法执行时间对比(解释执行 vs JIT编译后)
    • 斐波那契数列递归与迭代版本性能对比
    • 矩阵乘法计算演示

TieredCompilationDemo.java

  • 作用:演示分层编译的五个层级
  • 核心功能
    • 模拟第0层(解释执行)到第4层(C2优化编译)
    • 展示不同编译层级的优化策略
    • 编译阈值和计数器机制说明

2.2 AOT编译相关 (aot包)

AOTCompilationDemo.java

  • 作用:演示AOT(Ahead-of-Time)提前编译
  • 核心功能
    • 展示AOT编译的基本用法
    • 生成Jaotc编译命令文件
    • 对比AOT与JIT的启动时间和内存占用

AOTPerformanceTest.java

  • 作用:AOT与JIT性能对比测试
  • 核心功能
    • 矩阵乘法性能测试
    • 素数计算性能测试
    • 字符串处理性能测试
    • 集合操作性能测试
    • 排序算法性能测试

2.3 编译器优化技术 (optimization包)

MethodInliningDemo.java

  • 作用:演示方法内联优化
  • 核心功能
    • 展示内联前后的代码差异
    • 内联深度限制演示
    • 内联性能对比测试

EscapeAnalysisDemo.java

  • 作用:演示逃逸分析及相关优化
  • 核心功能
    • 无逃逸对象(栈上分配/标量替换)
    • 方法逃逸对象
    • 线程逃逸对象
    • 同步消除(锁消除)
    • 标量替换性能测试
    • 栈上分配性能测试

LoopOptimizationDemo.java

  • 作用:演示循环优化技术
  • 核心功能
    • 循环展开(Loop Unrolling)
    • 循环不变量外提(Invariant Code Motion)
    • 边界检查消除(Bounds Check Elimination)
    • 向量化优化(SIMD)
    • 性能对比测试

2.4 Graal编译器 (graal包)

GraalCompilerDemo.java

  • 作用:演示Graal编译器特性
  • 核心功能
    • 检测是否使用Graal编译器
    • 部分逃逸分析(Partial Escape Analysis)
    • Graal编译器使用指南
    • 性能测试

GraalPerformanceTest.java

  • 作用:Graal编译器性能测试
  • 核心功能
    • 快速排序算法测试
    • 素数筛法测试
    • 矩阵乘法测试
    • 蒙特卡洛计算PI
    • 斐波那契数列计算
    • 字符串处理测试
    • 对象创建测试

3. 测试方法

3.1 运行所有测试

bash
cd linsir-abc/linsir-abc-core
mvn test -Dtest=RuntimeCompilationTest

3.2 测试类说明

测试类 RuntimeCompilationTest.java 包含12个测试方法:

序号测试方法说明
1testHotSpotDetection测试热点代码探测
2testJITAnalysis测试JIT分析方法
3testTieredCompilation测试分层编译模拟
4testAOTCompilation测试AOT编译方法
5testAOTPerformance测试AOT性能测试类
6testMethodInlining测试方法内联
7testEscapeAnalysis测试逃逸分析
8testLoopOptimization测试循环优化
9testGraalCompiler测试Graal编译器检测
10testGraalPerformance测试Graal性能测试类
11testAllOptimizations测试所有编译优化技术
12testPerformanceComparison测试性能对比

3.3 单独运行演示类

JIT编译演示

bash
mvn exec:java -Dexec.mainClass="com.linsir.abc.core.jvm.runtime.jit.HotSpotDetector"
mvn exec:java -Dexec.mainClass="com.linsir.abc.core.jvm.runtime.jit.JITAnalysisDemo"
mvn exec:java -Dexec.mainClass="com.linsir.abc.core.jvm.runtime.jit.TieredCompilationDemo"

AOT编译演示

bash
mvn exec:java -Dexec.mainClass="com.linsir.abc.core.jvm.runtime.aot.AOTCompilationDemo"
mvn exec:java -Dexec.mainClass="com.linsir.abc.core.jvm.runtime.aot.AOTPerformanceTest"

编译器优化演示

bash
mvn exec:java -Dexec.mainClass="com.linsir.abc.core.jvm.runtime.optimization.MethodInliningDemo"
mvn exec:java -Dexec.mainClass="com.linsir.abc.core.jvm.runtime.optimization.EscapeAnalysisDemo"
mvn exec:java -Dexec.mainClass="com.linsir.abc.core.jvm.runtime.optimization.LoopOptimizationDemo"

Graal编译器演示

bash
mvn exec:java -Dexec.mainClass="com.linsir.abc.core.jvm.runtime.graal.GraalCompilerDemo"
mvn exec:java -Dexec.mainClass="com.linsir.abc.core.jvm.runtime.graal.GraalPerformanceTest"

3.4 使用不同JVM参数测试

查看JIT编译日志

bash
java -XX:+PrintCompilation -cp target/classes com.linsir.abc.core.jvm.runtime.jit.HotSpotDetector

禁用分层编译

bash
java -XX:-TieredCompilation -cp target/classes com.linsir.abc.core.jvm.runtime.jit.TieredCompilationDemo

使用Graal编译器(需GraalVM)

bash
java -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -cp target/classes com.linsir.abc.core.jvm.runtime.graal.GraalCompilerDemo

查看逃逸分析优化

bash
java -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+PrintEscapeAnalysis -cp target/classes com.linsir.abc.core.jvm.runtime.optimization.EscapeAnalysisDemo

4. 代码执行预期结果

4.1 测试执行结果

运行 mvn test -Dtest=RuntimeCompilationTest 预期输出:

[INFO] Tests run: 12, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS

性能对比输出示例:

性能对比(10000次迭代):
  JIT风格: 4 ms
  AOT风格: 3 ms
  Graal风格: 45 ms

4.2 HotSpotDetector 执行结果

=== 热点代码探测演示 ===

热点方法执行 1000 次
热点方法执行 10000 次
普通方法执行
OSR result: 333833500

=== 演示完成 ===
提示: 使用 -XX:+PrintCompilation 查看编译日志

4.3 JITAnalysisDemo 执行结果

=== JIT编译分析演示 ===

测试1: 简单计算
  计算结果: 328350
  执行时间: 0 ms

测试2: 斐波那契数列
  递归版本(30): 832040, 耗时: 5 ms
  迭代版本(30): 832040, 耗时: 0 ms

测试3: 矩阵乘法
  矩阵大小: 100x100
  计算结果: 24502500
  执行时间: 2 ms

=== 演示完成 ===

4.4 TieredCompilationDemo 执行结果

=== 分层编译演示 ===

编译层级说明:
  第0层: 解释执行
  第1层: C1简单编译
  第2层: C1受限编译
  第3层: C1完全编译
  第4层: C2优化编译

模拟分层编译过程:
  第0层 - 解释执行: 结果 = 4950
  第1层 - C1简单编译: 结果 = 4950
  第2层 - C1受限编译: 结果 = 4950
  第3层 - C1完全编译: 结果 = 4950
  第4层 - C2优化编译: 结果 = 4950

=== 演示完成 ===

4.5 EscapeAnalysisDemo 执行结果

=== 逃逸分析演示 ===

无逃逸对象示例:
  结果: 25
  说明: Point对象未逃逸,可进行栈上分配和标量替换

方法逃逸示例:
  结果: Point(3, 4)
  说明: Point对象逃逸到方法外部,必须在堆上分配

同步消除示例:
  结果长度: 80
  说明: StringBuffer的同步操作被消除

性能测试:
  标量替换测试: 耗时 5 ms
  栈上分配测试: 耗时 3 ms
  同步消除测试: 耗时 8 ms

=== 演示完成 ===
提示: 使用 -XX:+DoEscapeAnalysis 启用逃逸分析

4.6 LoopOptimizationDemo 执行结果

=== 循环优化演示 ===

循环展开示例:
  基础循环: 15
  展开循环: 15
  说明: JIT编译器自动进行循环展开优化

循环不变量外提示例:
  优化前概念: 每次迭代计算array.length
  优化后概念: 将不变量提取到循环外部

边界检查消除示例:
  结果: 15
  说明: 编译器证明不会越界,消除边界检查

性能对比:
  基础循环: 15 ms
  展开循环: 8 ms
  性能提升: 1.88x

=== 演示完成 ===

4.7 GraalCompilerDemo 执行结果

=== Graal编译器演示 ===

JVM信息:
  Java版本: 17.0.x
  JVM名称: OpenJDK 64-Bit Server VM
  使用Graal: false
  JVMCI启用: false

Graal编译器使用指南:
  1. 使用Graal作为JIT编译器:
     java -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler ...
  2. GraalVM Native Image:
     native-image -cp . HelloWorld

性能测试:
  计算密集型任务: 耗时 12 ms
  斐波那契计算: 结果 12586269025, 耗时 0 ms

=== 演示完成 ===
提示: 安装GraalVM并使用 -XX:+UseJVMCICompiler 参数运行

5. 关键JVM参数参考

5.1 JIT编译参数

参数说明
-XX:+PrintCompilation打印编译日志
-XX:+TieredCompilation启用分层编译(默认开启)
-XX:-TieredCompilation禁用分层编译
-XX:CompileThreshold=10000设置编译阈值
-XX:ReservedCodeCacheSize=256m设置代码缓存大小

5.2 编译器优化参数

参数说明
-XX:+DoEscapeAnalysis启用逃逸分析
-XX:+EliminateAllocations启用标量替换
-XX:+EliminateLocks启用同步消除
-XX:+UseLoopPredicate启用循环优化
-XX:+UseStringDeduplication启用字符串去重

5.3 Graal编译器参数

参数说明
-XX:+UseJVMCICompiler使用Graal编译器
-XX:+EnableJVMCI启用JVMCI接口
-XX:+PrintGC打印GC日志
-XX:+PrintCompilation打印编译日志

6. 注意事项

  1. Java版本要求:代码使用Java 8+特性,Graal编译器需要Java 9+或GraalVM
  2. 性能测试结果:实际性能数据因硬件、JVM版本、运行环境而异
  3. JIT编译触发:热点代码需要达到一定调用次数才会触发编译
  4. 逃逸分析:需要开启 -XX:+DoEscapeAnalysis(JDK 8默认开启)
  5. Graal编译器:需要安装GraalVM或使用 -XX:+UseJVMCICompiler 参数

Released under the MIT License.