JVM学习7: 执行引擎

执行引擎基础

概述

是JVM核心组成部分之一。

执行引擎是由软件实现的,因此可以不受物理条件制约地定制指令集和执行引擎结构体系,能够执行那些不被硬件直接支持的指令集格式。

JVM的主要任务就是装载字节码,但是字节码并不能够直接运行在操作系统上,因为字节码指令并非等价于本地机器指令,它内部包含的仅仅只是一些能够被JVM识别的字节码指令、符号表,以及一些辅助信息。

如果要让一个Java程序运行起来,执行引擎的任务就是将字节码指令解释/编译为对应平台上的本地机器指令才可以。简单来说,JVM的执行引擎充当了将高级语言翻译为机器语言的译者。

简单工作过程

从外观来看,所有的Java虚拟机的执行引擎输入输出都是一致的:输入的是字节码二进制流,处理过程是字节码解析执行的等效过程,输出是执行结果。

在这里插入图片描述

大部分程序代码转换为物理机的目标代码或虚拟机能执行的指令集之前,都需要以上步骤。

解释器和编译器

什么是解释器?什么是JIT编译器?

解释器:当Java虚拟机启动时,根据预定义的规范对字节码采用逐行解释的方式执行,将字节码文件的每条内容翻译为对应平台的本地机器指令来执行。JVM的设计者的初衷仅仅只是单纯为了满足Java程序实现跨平台特性,因此避免使用静态编译的方式直接生成本地机器指令,从而诞生了实现解释器在运行时采用逐行解释字节码执行程序的想法。由于解释器在设计和实现上非常简单,因此除了Java语言外,还有许多高级语言也基于解释器执行,比如Python、Ruby等。但是,基于解释器执行已经沦为低效的代名词。为了解决这个问题,JVM支持即时编译技术,目的是避免函数被解释执行,而是将整个函数编译成机器码,每次函数执行时,只执行编译后的机器码即可,这样可以提高执行效率。不过,基于解释器的执行模式仍然为中间语言的发展做出了不可磨灭的贡献。

JIT(Just In Time Compiler)编译器:就是虚拟机将源代码直接编译成和本地机器平台相关的机器语言。

解释器工作机制

就是一个运行时翻译者,将字节码文件中的内容翻译为对应平台的本地机器指令然后执行。

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

解释器分类:字节码解释器、模板解释器。

Java代码执行分类

由于存在即时编译技术,所以Java代码就出现了两种执行方式:

  • 通过解释器将字节码转换为机器码
  • 通过即时编译器将方法编译成机器码

Hotspot VM是目前高性能虚拟机的代表之一,它使用解释器与即时编译器并存的架构。在Java虚拟机运行时,解释器和即时编译器能够互相协作,各自取长补短,尽力选择最合适的方式来权衡编译本地代码的时间和直接解释执行代码的时间。

Java的半解释半编译语言

JDK1.0时代,将Java语言定位为解释执行还是比较准确的。后来Java也发展出了直接生成本地代码的编译器。

现在的JVM在执行Java代码时,通常会将解释执行和编译执行结合起来。

在这里插入图片描述

解释器和编译器并存

为什么解释器和编译器二者是并存的,而不是只使用编译器执行代码?

当程序启动时,解释器可以马上发挥作用,省去编译时间,立即执行。

编译器想要发挥作用,把代码编译成本地代码,需要一定的执行时间,但是编译为本地代码后,执行效率就很高了。

所以JRockit VM就不包含解释器,只有编译器,执行效率很高,但是启动时需要花费更长的时间来编译。对于服务端应用来说,启动时间不是关注重点,但是对于那些看重启动时间的应用来说,使用解释器和编译器相结合的方式是正确的。

在Java虚拟机启动时,解释器可以首先发挥作用,而不必等待即时编译器全部编译完成才能够执行,这样可以省去许多不必要的时间消耗,编译器把越来越多的代码编译成本地代码后,执行效率也会更高。

同时,解释执行在编译器进行激进优化不成立的时候,作为编译器的逃生门。

机器码、汇编

机器码

各种使用二进制编码方式表示的指令,叫做机器指令码,最开始,人们使用它来编写程序,这就是机器语言。

机器语言不容易理解和记忆,并且容易出错。

用它编写的程序输入计算机,CPU直接读取运行,因此和其他语言编写的程序相比,执行速度最快。

机器指令与CPU紧密相关,所有不同种类的CPU所对应的机器指令也就不同。

指令

由于机器码是由0和1组成的二进制序列,可读性差,所以出现了指令。

指令就是把机器码中特定的0和1序列简化成对应的指令。

由于不同的硬件平台执行同一个操作对应的机器码可能不同,所以不同的硬件平台的同一指令所对应的机器码可能不同。

指令集

不同硬件平台,各自支持的指令是存在差别的,因此每个平台所支持的指令,称为对应平台的指令集。

常见x86指令集和ARM指令集。

汇编语言

由于指令的可读性还是太差,于是出现了汇编语言。

在汇编语言中,使用助记符代替机器指令的操作码,使用地址符号或标记代替指令或操作数的地址。

在不同的硬件平台,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令。

由于计算机只认识指令码,所以使用汇编语言编写的程序还必须翻译成机器指令码,才能被计算机识别、运行。

高级语言

为了使计算机编程更加简单,出现了各种高级编写语言。比机器语言、汇编语言更接近人类的语言。

当计算机执行高级语言编写的程序时,仍然需要把程序解释和编译成机器的指令码,完成这个过程的程序就叫做解释程序或编译程序。

在这里插入图片描述

字节码

字节码是一种中间状态的二进制代码,比机器码更抽象,需要直译器转译后才能成为机器码。

字节码主要为了实现特定软件运行和软件环境、与硬件环境无关。

字节码的实现方式是通过编译器和虚拟机器,编译器将源码转译成字节码,特定平台的虚拟机器将字节码转译为可以执行的指令。

JIT编译器

概述

Java语言的编译期其实是一段不确定的操作过程,因为它可能是指一个前端编译器把.java文件转变为.class文件的过程。

也可能是指虚拟机的后端运行期编译器把字节码转变为机器码的过程。

还可能是指使用静态提前编译器直接把.java文件编译成本地机器码的过程。

热点代码及探测

是否需要启动JIT编译器将字节码直接编译成对应平台的机器指令,则需要根据代码被调用执行的频率而定。

关于那些需要被编译成本地代码的字节码,也被称为热点代码,JIT编译器在运行时会针对那些调用频繁的热点代码做出深度优化,将其直接编译为对应平台的本地机器码指令,以此提升Java程序的执行效率。

一个被多次调用的方法,或者是一个方法内部循环执行较多的循环体都可以被称为热点代码,因此都可以通过JIT编译器编译成本地机器指令。

由于这种编译方式发生在方法的执行过程中,因此也被称为栈上替换,或称为栈上编译。

一个方法被调用多少次或者一个循环体执行多少次才可以达到热点代码的标准呢?

这依靠热点代码探测功能。

目前Hotspot VM使用的热点探测方式基于计数器实现。

使用基于计数器的热点探测,Hotspot VM将会为每个方法建立两个不同类型的计数器,分别为方法调用计数器和回边计数器。

  • 方法调用计数器用于统计方法调用次数。
  • 回边计数器用于统计循环体执行次数。

方法调用计数器

用于统计方法调用次数。

默认在client模式下是1500次,在server模式下是10000次,超过这个阈值,就会触发JIT编译。

可以使用-XX:CompileThreshold来设置阈值。

当一个方法被调用时,先检查是否被编译过,如果是,则优先使用编译的本地代码执行。如果没有,则将此方法的调用计数器+1,然后判断方法调用计数器和回边计数器之和是否超过方法调用计数器阈值,如果超过,将会向即时编译器提交一个该方法的代码编译请求。

热度衰减

如果不做任何设置,方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,即一段时间内方法被调用的次数。当超过一定的时间限度,如果方法的调用次数仍然不足以提交JIT编译,这个方法的调用计数器就会被减少一半,这个过程称为方法调用计数器热度衰减,而这段时间就称为方法统计的半衰周期。

进行热度衰减动作是虚拟机进行垃圾回收时做的,可以使用虚拟机参数-XX:-UseCounterDecay来关闭热度衰减,让方法计数器统计方法调用的绝对次数。

另外,可以使用-XX:CounterHalfLifeTime参数设置半衰周期时长,单位是秒。

回边计数器

用于统计循环体执行次数,在字节码中遇到控制流向后跳转的指令被称为回边。显然,建立回边计数器统计目的就是为了触发OSR编译。

Hotspot VM设置执行方式

  • -Xint - 完全使用解释器执行程序
  • -Xcomp - 完全使用即时编译器执行程序,如果出现问题,再使用解释器
  • -Xmixed - 混合模式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值