第11章 后端编译与优化

第11章 后端编译与优化

11.2 即时编译器

  • 当虚拟机发现某个方法或代码块的运行特别频繁,就会把这些代码认定为“热点代码(Hot Spot Code)”,为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成本地机器码,并以各种手段尽可能地进行代码优化,在运行时完成这个任务的后端编译器被称为即时编译器。
11.2.1 解释器与编译器
  • 解释器与编译器搭配使用的方式在虚拟机中被称为“混合模式”,用户可以用参数“-Xint”强制虚拟机运行于“解释模式”,这时候编译器完全不介入工作,全部代码都使用解释方式执行;另外,也可也使用参数“-Xcomp”强制虚拟机运行于“编译模式”,这时候将优先采用编译方式执行程序,但是解释器仍然要在编译无法进行的情况下介入执行过程。
  • 为了在程序启动响应速度与运行效率之间达到最佳平衡,加入了分层编译的功能
11.2.2 编译对象与触发条件
  • 热点代码主要有两类,包括:

    • 被多次调用的方法
    • 被多次执行的循环体
    • 对于这两种情况,编译的目标对象都是整个方法体。
  • 对于循环体这种编译方式,因为编译发生在方法执行的过程中,因此被很形象地称为“栈上替换”,即方法的栈帧还在栈上,方法就被替换了。

  • 目前主流的热点探测判定方式有两种,分别是:

    • 基于采样的热点探测
    • 基于计数器的热点探测
  • HotSpot虚拟机使用的是第二种基于计数器的热点探测方法,为了实现热点计数,HotSpot为每个方法准备了两类计数器:方法调用计数器(计数热度衰减)和回边计数器(没有计数热度衰减的过程)(“回边“的意思就是指在循环边界往回跳转)

  • 计数器的阈值可以通过-XX:CompileThreshold来人为设定

  • 栈上替换(OSR)

11.2.3 编译过程
  • 在后台编译的过程中,服务端编译器和客户端编译器的编译过程是有所差别的。对于客户端编译器来说,它是一个相对简单快速的三段式编译器,主要的优点在于局部性的优化,而放弃了许多耗时较长的全局优化手段。

11.3 提前编译器

  • 目前提前编译产品和对其的研究有着两条明显的分支,一条分支是做与传统C,C++编译器类似的,在程序运行之前把程序代码编译成机器码的静态翻译工作;另外一条分支是把原本即时编译器在运行时要做的编译工作提前做好并保存下来,下次运行到这些代码时直接把它加载进来使用。

11.4 编译器优化技术

11.4.2 方法内联
11.4.3 逃逸分析
  • 逃逸分析是目前Java虚拟机中比较前沿的优化技术,它与类型继承关系分析一样,并不是直接优化代码的手段,而是为其他优化措施提供依据的分析技术
  • 若一个数据已经无法再分解成更小的数据来表示了,Java虚拟机中的原始数据类型(int,long等数据类型以及reference类型等)都不能再进一步分解了,那么这些数据就可以被称为标量。相对的,如果一个数据可以继续分解,那它就被称为聚合量,Java中的对象就是典型的聚合量。
11.4.4 公共子表达式消除
  • 公共子表达式消除是一项非常经典的,普遍应用于各种编译器的优化技术,它的含义是:如果一个表达式E之前已经被计算过了,并且从先前的计算到现在E中所有变量的值都没有发生变化,那么E的这次出现就称为公共子表达式。
11.4.5 数组边界检查消除
  • 数组边界检查优化尽可能把运行期检查提前到编译期完成
  • 隐式异常处理:Java中空指针检查和算术运算中除数为零的检查都采用了这种方案。

11.5 实战

  • 从编译器内部来看即:字节码–理想图—优化----机器码

你可能感兴趣的:(java,jvm)