概述

1、执行引擎是Java虚拟机的核心组成部分之一

2、执行引擎的任务是将字节码指令解释/编译为对应平台上的本地机器指令 (其实执行引擎就是将高级语言翻译为机器语言)

3、执行引擎的工作过程

  • 输入的是字节码二进制流
  • 处理过程是字节码解析执行的等效过程
  • 输出是执行结果

4、执行引擎在执行的过程中需要执行的字节码指令完全 依赖于PC寄存器

5、每当执行完一项指令操作后,PC寄存器就会更新下一条需要被执行的指令地址

6、在方法的执行过程中,执行引擎有可能会通过存储在局部变量表中的对象引用定位到存储在java堆中的对象实例信息,以及通过对象头中的元数据指针定位到目标对象的类型信息

7、执行引擎包括解释器,及时编译器,垃圾回收器


java代码编译和执行的过程

大部分的程序代码转换成物理机的目标代码或虚拟机能执行的指令集之前,都需要经过下图的各个步骤

解释器:

​ 当java虚拟机启动时会根据预定义的规范对字节码采用逐行解释的方式执行

​ 将字节码文件中的内容翻译为对应平台的本地机器指令执行

JIT编译器:

​ 虚拟机将源代码直接编译成和本地机器平台相关的机器语言


机器码、指令、汇编语言

机器码

各种用二进制编码方式表示的指令称为机器指令码(机器语言)

编写的程序输入计算机,CPU直接读取运行,执行速度相比其他语言最快,而且机器指令和CPU密切相关,不同种类的CPU机器指令不同


指令

由于机器码是由0,1组成的二进制序列,为了增加可读性,将机器码中特定的0,1序列简化为对应的指令。

不同的硬件平台的同一种指令,对应的机器码也可能不同


指令集

每个平台所支持的指令称为对应平台的指令集

例如:

x86指令集 -> 对应x86架构的平台

ARM指令集 -> 对应ARM架构的平台


汇编语言

使用助记符代替机器指令的操作码,用地址符号或标号替代指令或操作数的地址


高级语言

计算机执行高级语言编写的程序时,需要将程序解释和编译成机器的指令码。(这个过程称为解释程序或编译程序)


字节码

1、字节码其实是一种中间状态(中间码)的二进制代码(文件),它比机器码更抽象,需要直译器转译后才能称为机器码

2、字节码的实现方式是编译器和虚拟机器(编译器将源码翻译成字节码,特定平台上的虚拟机器将字节码转义为可以直接执行的指令)

主要目的是为了实现跨平台性


解释器

1、利用解释器来逐行解析字节码文件,其实解释器的作用就是将字节码文件中的内容翻译为对应平台的本地机器指令执行

2、当一条字节码指令被解释执行完成后,接着再根据PC寄存器中记录的下一条需要被执行的字节码指令执行解释操作

分类(*)

字节码解释器:执行时通过纯软件代码模拟字节码执行,效率低下

模板解释器:将每一条字节码和一个模板函数相关联,模板函数直接产生该字节码执行时的机器码,效率较高

注意:

1、无论是哪种解释器,效率还是比即时编译器低的

2、解释器存在的必要性:程序启动后,解释器可以马上发挥作用,省去编译的时间,立即执行。 编译器要想发挥作用,把代码编译成本地代码,需要一定的执行时间。当Java虚拟器启动时,解释器可以首先发挥作用,而不必等待即时编译器全部编译完成后再执行,这样可以省去许多不必要的编译时间。在一定时间过后,编译器发挥作用,把越来越多的代码编译成本地代码,获得更高的执行效率。


JIT编译器

前端编译器:将 .java 文件转变成 .class 文件的过程

后端编译器(JIT编译器):将字节码转变成机器码的过程

静态提前编译器(AOT编译器):直接将 .java 文件编译成本地机器代码的过程


热点代码及探测方式

1、决定是否启用 JIT 编译器需要根据代码被调用执行的频率而定。关于需要被编译为本地代码的字节码,称为”热点代码“

2、JIT 编译器运行时会针对那些频繁被调用的热点代码做深度优化,将其直接编译为对应平台的本地机器指令,提高执行性能

热点代码:

一个多次调用的方法或者方法体内循环次数较多的循环体都可以称为热点代码(这种编译方式由于发生在方法的执行过程中,因此也被称为栈上替换,OSR)


基于计数器的热点探测

判断一个方法被调用多少次,或循环体循环多少次才能称为热点代码的标准

HotSpot虚拟机为每个方法都创建两个不同类型的计数器

方法调用计数器

统计方法的调用次数,可以通过参数 -XX:CompileThreshold进行设定,Client默认是1500次,Server默认是10000次,超过阈值,触发 JIT 编译


热度衰减

方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率 (一段时间内方法的执行频率)当超过一定限度时,如果方法的调用次数不足让它提交给即时编译器,那么这个方法的调用计数器就会减少一半,这个过程称为调用计数器热度的衰减这段时间就称为该方法统计的半衰周期

关闭热度衰减:-XX:UseCounterDecay

设置半衰期的时间:-XX:CounterHalfLifeTime(单位为s)


回边计数器

统计循环体的循环次数


设置程序执行方式

-Xint:完全采用解释器模式执行程序

-Xcomp:完全采用即时编译器(如果即时编译器出现问题,解释器会介入执行)

-Xmixed:采用解释器+即时编译器的混合模式


JIT分类

Client Compiler和Server Compiler(简称为C1和C2)

C1

-client:指定运行在Client模式下,C1会对字节码进行简单可靠的优化,耗时短

C2

-server:指定运行在Server模式下,C2进行耗时较长的优化以及激进优化,但优化的代码执行效率更高

C1和C2的优化策略(*)

Graal编译器与AOT编译器(*)