JIT 入门
一.jit
全称:just in time compiler.java 即时编译器.通过监测jvm在解释运行过程中代码执行的频率.将认定的热点代码通过优化直接编译为机器
代码并保留下.当再次执行时直接运行相应代码.
1.1知识回顾
这里其实需要从代码的运行来讲.我们都知道cpu只能识别机器码.而诸如c++,java都是比较接近人类语言的高级语言.
c++在执行过程中,直接可以编译得到机器可以直接运行的.但在实际的编程过程中需要考虑平台cpu架构[x86与x64]的适配.即使得到编译后的二进制文件
.通常情况下也无法在多个平台都可以运行起来.
相比之下java在推出的过程中为了达到write once,run in anywhere.因为这样一来实际的编程开发者无需考虑具体的cpu架构,更多的去关心
实际的业务开发.通过先编译得到字节码.也就是.class文件.然后通过jvm解释运行.虚拟机在中间解决了平台的差异.但是这样一来,相当于在中间插入
了编译为字节码的过程,拉长整个执行流程.每次在执行过程中通过编译,解释这样的过程降低了java的执行效率.而有些时候部分代码并不是每次都会
做出修改.能不能不要每次都执行编译,而jit就是这样一个技术,帮助java代码执行编译执行过程中,减少编译的过程,部分的代码编译为机器码后通过一
定的规则保留下来,下次执行从而直接执行,从而提高整体java的运行效率.
那么问题来了,哪些代码会被jit带走成为机器码呢?
1.2整体流程
然而并不是所有的代码都需要被选中成为机器码的.首先jit在执行编译将字节码保留成为机器码的过程也是需要耗费机器的性能.当一些未来可能仅仅执行
一次的代码是不需要被成为热点代码,成本收益不高.再说在启动的时候,往往会追求应用的启动速度这时候也是尽可能的去少占用机器的性能,这时候可能
解释运行反而更快.这样来看并不是西瓜什么时候吃,都是甜的.也是需要分场景的.
二.编译优化策略
2.1 c1,c2
jit 在运行时决定使用哪种编译模式来进行.c1 的相对的启动速度较快,常用以GUI的应用程序.c2 的启动速度较慢多用以处理后端企业级应用程序.
同样的代码在c1,c2两种模式下可能得到不同的机器码.1.7之后在结合两者的优势之后,更多的则是在启动的时候使用c1,而在等到服务器启动之后改用
c2的策略来进行编译.
- java 9
AOT(Ahead of Time)用以在程序运行前进行静态编译,避免在运行时进行性能和资源竞争.
- java 10
Graal 一个纯由Java 编写的 编译器.有兴趣可以了解下.
2.1 方法内联
在方法调用的的过程,经常回出现一些方法内部调用了一个比较小的方法函数.这样的情况可能在多次执行之后会通过jit的优化策略进行方法内联的转换.
如:
private int first(int x1, int x2, int x3, int x4) {
return add2(x1, x2) + add2(x3, x4);
}
private int first(int x1, int x2) {
return x1 + x2;
}
private int after(int x1, int x2, int x3, int x4) {
return x1 + x2 + x3 + x4;
}
在进行调用的次数统计上.使用client编译器时,默认为1500; 使用server编译器时,默认为10000;
2.2 栈上分配
JAVA变量默认是分配在主存的堆上,但是如果方法中的变量未逃出使用的生命周期,不会被外部方法或者线程引用.可以考虑在栈上分配内存.
减少GC压力,另外逃逸分析可以实现锁优化等提升性能方法.如果对象为堆分配且仅被单一方法访问(inlining的重要性再次体现) ,则可将该对象转化成栈分配
上一篇: Java基础编程-枚举类与注解
下一篇: Java基础编程-02基本语法