11. 执行引擎
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6DOHEP03-1603946753415)(C:\Users\GO FOR IT\AppData\Roaming\Typora\typora-user-images\1603766974528.png)]](http://image109.360doc.com/DownloadImg/2021/10/3003/233005199_1_20211030031331351)
11.1 执行引擎概述
11.2 执行引擎的工作过程
- 执行引擎在执行的过程中究竟需要执行什么样的字节码指令完全依赖于PC寄存器。
- 每当执行完一项指令操作后,PC寄存器就会更新下一条需要被执行的指令地址。
- 当然方法在执行的过程中,执行引擎有可能会通过存储在局部变量表中的对象引用准确定位到存储在Java堆区中的对象实例信息,以及通过对象头中的元数据指针定位到目标对象的类型信息。
11.3 java代码编译和执行的过程
为什么说java是半编译半解释?
执行java代码时,通常通常都会将解释执行和编译执行二者结合。
机器码:
- 各种用二进制编码方式表示的指令,叫做机器指令码。开始,人们就用它采编写程序,这就是机器语言。
- 机器语言虽然能够被计算机理解和接受,但和人们的语言差别太大,不易被人们理解和记忆,并且用它编程容易出差错。
- 用它编写的程序一经输入计算机,CPU直接读取运行,因此和其他语言编的程序相比,执行速度最快。
- 机器指令与CPU紧密相关,所以不同种类的CPU所对应的机器指令也就不同。
指令:
- 指令就是把机器码中特定的0和1序列,简化成对应的指令。
- 不同平台的同一种指令对应的机器码可能不一样。
指令集:
- 不同的硬件平台,各自支持的指令,是有差别的。因此每个平台所支持的指令,称之为对应平台的指令集。
- 常见的有:x86指令集和ARM指令集。
11.4 JIT编译器
- HotSpot VM采用解释器与即时编译器并存的架构。
为什么要保留解释器来“拖累”程序的执行性能?
程序刚启动的时候,解释器就会立即执行,响应速度快,各有优缺点。
选择JIT编译还是解释器?
当然是否需要启动JIT编译器将字节码直接编译为对应平台的本地机器指令,则需要根据代码被调用执行的频率而定。关于那些需要被编译为本地代码的字节码,也被称之为“热点代码”,JIT编译器在运行时会针对那些频繁被调用的“热点代码”做出深度优化,将其直接编译为对应平台的本地机器指令,以此提升Java程序的执行性能。
- 一个被多次调用的方法,或者是一个方法体内部循环次数较多的循环体都可以被称之为“热点代码”,因此都可以通过JIT编译器编译为本地机器指令。调用多少次能达到标准,依靠热点探测功能。目前HotSpot VM所采用的热点探测方式是基于计数器的热点探测。
HotSpot VM为每个方法建立两个计数器,分为方法调用计数器和回边计数器。
-
方法调用计数器用于统计方法的调用次数。 -
回边计数器则用于统计循环体执行的循环次数。
11.5 方法调用计数器
- 统计方法被调用的次数,默认阈值在Client模式下是1500次,Sever模式下是10000次,超过这个阈值就会触发JIT编译。
如果不做任何设置,方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,即一段时间之内方法被调用的次数。当超过一定的时间限度,如果方法的调用次数仍然不足以让它提交给即时编译器编译,那这个方法的调用计数器就会被减少一半,这个过程称为方法调用计数器热度的衰减(Counter Decay),而这段时间就称为此方法统计的半衰周期(counter Half Life Time)。
-XX:-UseCounterDecay 来关闭热度衰减。
-XX:CounterHalfLifeTime 参数设置半衰周期的时间,单位是秒。
11.6 回边计数器
- 它的作用是统计一个方法中循环体代码执行的次数,在字节码中遇到控制流向后跳转的指令称为“回边”(Back Edge)。显然,建立回边计数器统计的目的就是为了触发OSR编译。

-Xint :完全采用解释器模式执行程序; -xcomp :完全采用即时编译器模式执行程序。如果即时编译出现问题,解释器会介入执行。 -Xmixed :采用解释器+即时编译器的混合模式共同执行程序。
11.6 HotSpot JM中JIT分类
在HotSpot VM中内嵌有两个JIT编译器,分别为client Compiler和serverCompiler,但大多数情况下我们简称为C1编译器和C2编译器。
C1和C2编译器不同的优化策略:
11.7 总结
- 一般来讲,JIT编译出来的机器码性能比解释器高。
- C2编译器启动时长比c1编译器慢,系统稳定执行以后,c2编译器执行速度远远快于c1编译器。
|