HotSpot虚拟机之后端编译与优化

目录

一、解释器与编译器

二、即时编译器

1. 热点代码

2. 编译过程

三、编译器优化技术

1. 方法内联

2. 逃逸分析

3. 公共子表达式

4. 数组边界检查消除

四、参考资料


 

一、解释器与编译器

        HotSpot虚拟机采用解释器与编译器并存的运行架构,如下表所示两者特点。

解释与编译器

特点

解释器

1.目的:字节码文件转为本地机器码,如:javac编译后,解释器解释;

2.优点:程序可以迅速启动和执行,省去编译的时间,立即运行

编译器

1.目的:即时编译出优化程度更高的本地机器码,但花费时间也会越长

2.HotSpot虚拟机内置两个或三个即时编译器,其中两个即时编译:

   C1编译器:客户端编译器(Client Compiler);

   C2编译器:服务端编译器(Server Compiler),JDK10的Graal替换C2;

注意:

   a.JVM中一般采用“混合模式”(mixed mode):解释器与编译器搭配使用;

   b.参数-client、-server强制JVM运行在客户端模式,还是服务端模式。

        输出代码优化质量的高低决定编译器是否优秀的关键,编译器分为:前端编译器(将Java源码转变成字节码的过程,只完成源码到抽象语法树或字节码的生成,如:javac命令)、后端编译器(完成代码优化及字节码生成本地机器码的过程,如:即时编译、提前编译都是后端编译器)。后端编译器完成热点代码的编译,又分为即时编译、提前编译;而HotSpot即时编译内置不同模式下的C1、C2编译。

        即时编译最大缺点是运行时编译占用程序运行时间或运算资源,为了提高效率,则提前编译器编译后提前保存(即时编译缓存),运行时则直接加载使用。

        JDK7在服务端模式,默认开启编译策略,即:分层编译,根据编译、优化的规模与耗时划分出不同的层次,如下图所示编译分层及交互关系。

二、即时编译器

1. 热点代码

        程序运行过程中对“热点代码”进行即时编译,所以即时编译的对象是热点代码。热点代码有:多次调用方法、多次执行的循环体,如下表所示。

热点代码分类

特点

被多次调用的方法

整个方法体作为编译对象(标准的即时编译方式)

被多次执行的循环体

1.热点代码只是方法体的一部分,但是以整个方法作为编译对象

2.“栈上替换”:虽然以整个方法作为编译对象,但是执行入口(从方法第几条字节码指令)不同,编译时会传入执行入口点字节码序号。这种编译发生在方法执行过程中,即:方法的栈帧还在栈中,方法被替换

注意:

    a.运行时,即时编译的目标是“热点代码”,有更好的优化;

    b.“栈上替换”:方法的栈帧还在栈中,方法被替换;

    c.上述两种热点代码,都是以整个方法作为编译对象,但是执行入口不同

        注意:以上两种热点代码,编译的对象都是整个方法体,而不是单独的循环体。若是循环体,执行入口(从方法第几条字节码指令开始执行)会稍有不同。

        那么什么时候触发即时编译呢?即热点代码探测技术,其分为:采样、计数器(JVM采用),如下表所示。

热点代码探测

特点

采样

1.实现:周期性检查各线程的调用栈顶,发现某个方法经常出现,则为热点;

2.优点:简单高效;易获取方法调用关系;

   缺点:很难精确方法热度,易受线程阻塞干扰

计数器

(HotSpot使用)

1.实现:每个方法(或代码块)建计数器,某时间段内统计执行次数,超出该阈值,则为热点

2.优点:更加精确严谨;

   缺点:实现复杂(维护计数器);不能直接获取方法调用关系;

3.HotSpot每个方法有两类计数器:方法调用计数器、回边计数器

   a.方法调用计数器:参数-XX:CompileThreshold(客户端模式1500次;服务端模式10000次);热度衰减(衰减操作在GC时触发)

   b.回边计数器:不同模式下回边阈值统计不同;绝对次数,没有热度衰减。

注意:

   a.“回边”(Back Edge):字节码控制流遇到向后跳转的指令

   b.回边次数不等于循环次数,如:空循环(自己跳转到自己的过程)

   c.HotSpot两类计数器触发即时编译,见下图。

2. 编译过程

        即时编译代码优化是建立在中间表示或机器码之上,而不是直接在源码或字节码做优化,如下图所示编译过程,共三个阶段:字节码生成HIR(High-Level Intermediate Representation _ 高级中间代码)、HIR生成LIR(Low-Level Intermediate Representation _ 低级中间代码)、LIR生成本地机器码。

三、编译器优化技术

1. 方法内联

        方法内联被称为“优化之母”,为其他优化建立良好的基础。方法内联是把目标方法的代码“复制”到主调方法之中,避免发生真实的方法调用

2. 逃逸分析

        逃逸分析有方法逃逸、线程逃逸两种: 

  • 方法逃逸:方法内定义一个对象,它可能被其他方法所引用,如:调用参数传递到其他方法
  • 线程逃逸:线程内定义一个对象,它可能被另一线程所访问,如:赋值可被其他线程访问。 

3. 公共子表达式

        表达式E已经被计算过,且从先前到现在E中所有变量没有改变,则E这次出现称为“公共子表达式”。

4. 数组边界检查消除

        每次访问数组元素时都要边界检查(性能负担),提高效率则编译期间完成边界检查。

四、参考资料

HotSpot虚拟机之Class文件及字节码指令_爱我所爱0505的博客-CSDN博客 

HotSpot虚拟机之类加载过程及类加载器_爱我所爱0505的博客-CSDN博客 

HotSpot虚拟机之字节码执行引擎_爱我所爱0505的博客-CSDN博客 

什么是即时编译_MariaOzawa的博客-CSDN博客

JIT即时编译器_rockvine的博客-CSDN博客

逃逸分析之标量替换_chengqiuming的博客-CSDN博客

JVM系列之:深入学习方法内联 - 知乎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值