16JIT即时编译器

1.C1、C2优化器

在Java中,JIT即时编译器是一项用来提升应用程序代码执行效率的技术。字节码指令被 Java 虚拟机解释执行,如果有一些指令执行频率高,称之为热点代码,这些字节码指令则被JIT即时编译器编译成机器码同时进行一些优化,最后保存在内存中,将来执行时直接读取就可以运行在计算机硬件上了。

在HotSpot中,有三款即时编译器,C1、C2和Graal,其中Graal在GraalVM章节中已经介绍过。

C1编译效率比C2快,但是优化效果不如C2。所以C1适合优化一些执行时间较短的代码,C2适合优化服务端程序中长期执行的代码。

JDK7之后,采用了分层编译的方式,在JVM中C1和C2会一同发挥作用,分层编译将整个优化级别分成了5个等级。

等级使用的组件描述保存的内容性能打分(1 – 5)
0解释器解释执行记录方法调用次数及循环次数1
1C1即时编译器C1完整优化优化后的机器码4
2C1即时编译器C1完整优化记录方法调用次数及循环次数优化后的机器码部分额外信息:方法调用次数及循环次数3
3C1即时编译器C1完整优化记录所有额外信息优化后的机器码所有额外信息:分支跳转次数、类型转换等等2
4C2即时编译器C2完整优化优化后的机器码5


JIT编译器主要优化手段是方法内联和逃逸分析。

2.方法内联

方法内联(Method Inline):方法体中的字节码指令直接复制到调用方的字节码指令中,节省了创建栈帧的开销。

3.逃逸分析

逃逸分析指的是如果JIT发现在方法内创建的对象不会被外部引用,那么就可以采用锁消除、标量替换等方式进行优化。

这段代码可以使用逃逸分析进行优化,因为test对象不会被外部引用,只会在方法中使用。

这段代码就会有一定的问题,如果在方法中对象被其他静态变量引用,那优化就无法进行。

锁消除

逃逸分析中的锁消除指的是如果对象被判断不会逃逸出去,那么在对象就不存在并发访问问题,对象上的锁处理都不会执行,从而提高性能。比如如下写法

锁消除优化在真正的工作代码中并不常见,一般加锁的对象都是支持多线程去访问的。

标量替换

逃逸分析真正对性能优化比较大的方式是标量替换,在Java虚拟机中,对象中的基本数据类型称为标量,引用的其他对象称为聚合量。标量替换指的是如果方法中的对象不会逃逸,那么其中的标量就可以直接在栈上分配。

如下图中,point对象不存在逃逸,那么就可以将test方法中的字节码指令直接挪到循环中,减少方法调用的开销。

4.总结

根据JIT即时编器优化代码的特性,在编写代码时注意以下几个事项,可以让代码执行时拥有更好的性能:

1、尽量编写比较小的方法,让方法内联可以生效。

2、高频使用的代码,特别是第三方依赖库甚至是JDK中的,如果内容过度复杂是无法内联的,可以自行实现一个特定的优化版本。

3、注意下接口的实现数量,尽量不要超过2个,否则会影响内联的处理。

4、高频调用的方法中创建对象临时使用,尽量不要让对象逃逸。

13 条评论

  1. Caden2494 2025-11-28 11:48 回复
  2. Sandra3344 2025-11-29 07:29 回复
  3. Meagan3533 2025-11-30 19:31 回复
  4. Adele4399 2025-12-02 10:22 回复
  5. Anastasia4041 2025-12-03 10:38 回复
  6. Joy1976 2025-12-17 15:20 回复
  7. Noah1804 2025-12-17 21:35 回复
  8. Kristina Wright

    I want to to thank you for this excellent read!! I certainly loved every bit of it. I have you bookmarked to check out new stuff you

    2025-12-20 11:26 回复
  9. Earl3607 2025-12-22 09:35 回复
  10. Martha2089 2025-12-26 04:23 回复

回复 Adele4399 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注