一、编译过程

1、默认条件

A: 编译器还未完成编译之前,都仍然将按照解释方式继续执行代码。(方法调用的标准编译请求 、栈上替换的编译请求)

B: 编译动作则在后台的编译线程中进行。

C: 可以通过参数-XX:-BackgroundCompilation来禁止后台编译,后台编译被禁止后,当达到触发即时编译的条件时,执行线程向虚拟机提交编译请求以后将会一直阻塞等待,直到编译过程完成再开始执行编译器输出的本地代码。

二、客户端编译器(三段式编译器)

1、一个平*立的前端将字节码构造成一种高级中间代码表示(High-Level Intermediate Representation,HIR,即与目标机器指令集无关的中间表示)。

A: HIR使用静态单分配(Static Single Assignment,SSA)的形式来代表代码值,这可以使得一些在HIR的构造过程之中和之后进行的优化动作更容易实现。在这之前编译器已经会在字节码上完成一部分基础优化,如方法内联、常量传播等优化将会在字节码被构造成HIR之前完成。

2、一个平台相关的后端从HIR中产生低级中间代码表示(Low-LevelIntermediate Representation,LIR,即与目标机器指令集相关的中间表示)

A: ,而在此之前会在HIR上完成另外一些优化,如空值检查消除、范围检查消除等,以便让HIR达到更高效的代码表示形式。

3、在平台相关的后端使用线性扫描算法(Linear Scan RegisterAllocation)在LIR上分配寄存器,并在LIR上做窥孔(Peephole)优化,然后产生机器代码。

【深入理解Java 虚拟机之 即时编译器】1123 编译过程

三、服务端编译

1、服务端编译器则是专门面向服务端的典型应用场景,并为服务端的性能配置针对性调整过的编译器,是一个能容忍很高优化复杂度的高级编译器,几乎能达到GNU C++编译器使用-O2参数时的优化强度。

A: 它会执行大部分经典的优化动作,如:无用代码消除(Dead Code Elimination)、循环展开(Loop Unrolling)、循环表达式外提(Loop Expression Hoisting)、消除公共子表达式(CommonSubexpression Elimination)、常量传播(Constant Propagation)、基本块重排序(Basic Block Reordering)等,

B: 实施一些与Java语言特性密切相关的优化技术,如范围检查消除(Range Check Elimination)、空值检查消除(NullCheck Elimination,不过并非所有的空值检查消除都是依赖编译器优化的,有一些是代码运行过程中自动优化了)等。

C: 还可能根据解释器或客户端编译器提供的性能监控信息,进行一些不稳定的预测性激进优化,如守护内联(GuardedInlining)、分支频率预测(Branch Frequency Prediction)等,

2、服务端编译采用的寄存器分配器是一个全局图着色分配器,它可以充分利用某些处理器架构(如RISC)上的大寄存器集合。以即时编译的标准来看,服务端编译器无疑是比较缓慢的,但它的编译速度依然远远超过传统的静态优化编译器,而且它相对于客户端编译器编译输出的代码质量有很大提高,可以大幅减少本地代码的执行时间,从而抵消掉额外的编译时间开销,所以也有很多非服务端的应用选择使用服务端模式的HotSpot虚拟机来运行。

分类:

技术点:

相关文章: