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 |
| 1 | C1即时编译器 | C1完整优化 | 优化后的机器码 | 4 |
| 2 | C1即时编译器 | C1完整优化记录方法调用次数及循环次数 | 优化后的机器码部分额外信息:方法调用次数及循环次数 | 3 |
| 3 | C1即时编译器 | C1完整优化记录所有额外信息 | 优化后的机器码所有额外信息:分支跳转次数、类型转换等等 | 2 |
| 4 | C2即时编译器 | C2完整优化 | 优化后的机器码 | 5 |
JIT编译器主要优化手段是方法内联和逃逸分析。
2.方法内联
方法内联(Method Inline):方法体中的字节码指令直接复制到调用方的字节码指令中,节省了创建栈帧的开销。
3.逃逸分析
逃逸分析指的是如果JIT发现在方法内创建的对象不会被外部引用,那么就可以采用锁消除、标量替换等方式进行优化。
这段代码可以使用逃逸分析进行优化,因为test对象不会被外部引用,只会在方法中使用。
这段代码就会有一定的问题,如果在方法中对象被其他静态变量引用,那优化就无法进行。
锁消除
逃逸分析中的锁消除指的是如果对象被判断不会逃逸出去,那么在对象就不存在并发访问问题,对象上的锁处理都不会执行,从而提高性能。比如如下写法
锁消除优化在真正的工作代码中并不常见,一般加锁的对象都是支持多线程去访问的。
标量替换
逃逸分析真正对性能优化比较大的方式是标量替换,在Java虚拟机中,对象中的基本数据类型称为标量,引用的其他对象称为聚合量。标量替换指的是如果方法中的对象不会逃逸,那么其中的标量就可以直接在栈上分配。
如下图中,point对象不存在逃逸,那么就可以将test方法中的字节码指令直接挪到循环中,减少方法调用的开销。
4.总结
根据JIT即时编器优化代码的特性,在编写代码时注意以下几个事项,可以让代码执行时拥有更好的性能:
1、尽量编写比较小的方法,让方法内联可以生效。
2、高频使用的代码,特别是第三方依赖库甚至是JDK中的,如果内容过度复杂是无法内联的,可以自行实现一个特定的优化版本。
3、注意下接口的实现数量,尽量不要超过2个,否则会影响内联的处理。
4、高频调用的方法中创建对象临时使用,尽量不要让对象逃逸。
https://shorturl.fm/pykcE
https://shorturl.fm/QWVTj
https://shorturl.fm/uKN45
https://shorturl.fm/XS8LV
https://shorturl.fm/97kDM
https://shorturl.fm/wH4sT
https://shorturl.fm/GbNyD
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
https://shorturl.fm/XOo7e
https://shorturl.fm/6Nf91
Boost your income—enroll in our affiliate program today!
Unlock exclusive rewards with every referral—enroll now!
Start sharing, start earning—become our affiliate today!