1、执行引擎概述
执行引擎是java虚拟机核心组成部分之一。
虚拟机是一个相对与物理机的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和操作系统层面上的,而虚拟机的执行引擎则是由软件自行实现的,因此可以不受物理条件约定指令集与执行引擎的结构体系,能够执行那些不被硬件直接执行的指令集格式。
JVM的主要任务是负责装载字节码到其内部,但是字节码并不能直接运行在操作系统上,因为字节码并不等价于本地机器指令,它的内部包含的仅仅只是一些能够被jvm所识别的字节码指令、符号表,以及其他辅助信息。
那么,如果想要让一个java程序运行起来,执行引擎的任务就是将字节码指令解释/编译为对应平台上的本地机器指令才可以。简单来说,jvm中的执行引擎充当了将高级语言翻译为机器语言的译者。
执行引擎的工作过程
- 执行引擎在执行过程中究竟需要什么样的字节码指令完全依赖于pc寄存器
- 每当执行完一项指令操作后,pc寄存器就会更新下一条需要被执行的指令地址
- 当然方法在执行过程中,执行引擎有可能会通过存储在局部变量表中的对象引用准确定位到存储在Java堆中的对象实例信息,以及通过对象头中的元数据指针定位到目标对象的类型信息。
2、Java代码编译和执行过程
程序源码-》词法分析-〉单词流-》语法分析-〉抽象语法树
抽象语法树-》指令流(可选)-〉解释器-》解释执行
抽象语法树-〉优化器(可选)-》中间代码(可选)=〉生成器-》目标代码
问题:什么事解释器(interpreter),什么事JIT编译器?
解释器:当java虚拟机启动时会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容翻译为对应平台的本地机器指令执行。
JIT(Just in Time complier)编译器:就是虚拟机将源代码直接变异成和本地平台相关的机器语言。
问题:为什么说java是半编译半解释型语言?
jdk1.0时代,将java语言定义为解释执行还是比较准确的,再后来,java也发展出可以直接生成本地代码的编译器。
现在jvm在执行java代码的时候,通常都会将解释执行与编译执行二者结合起来进行。
3、机器码、指令、汇编语言
机器码:
各种用二进制编码方式表示的指令,叫做机器指令码。
指令:
机器吗可读性差,发明了指令。指令就是把机器吗中待定的0和1序列,简化成对应的指令。由于迎接平台不一样,机器吗也不同
指令集:
不同机器不一样
汇编语言:
指令的可读性还是差,又发明了汇编语言。
高级语言:
更接近人的语言。
仍然需要把程序解释和编译成机器指令。
C/C++源程序执行过程:
编译过程又可以分为两个阶段:编译和汇编。
编译过程:是读取源程序字节流,对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码。
汇编过程:实际上指把汇编语言代码翻译成目标机器指令的过程。
4、解释器
为了满足java程序实现跨平台特性,采用避免采用静态变异的方式直接生成本地机器指令,从而诞生了实现解释器在运行采用竹行解释自己饿吗执行程序的想法。
解释器工作机制或工作任务
承担翻译工作。
字节码解释器、模版解释器
纯软件代码
每条字节码和一个模板函数相关联。
看一个github-cpython
现状:
基于解释器执行已经沦为低效的代名词。
将整改函数编译成为机器码,每次函数执行时,只执行编译后的机器码即可,效率更高。
5、JIT编译器
java代码的执行分类
hotspot采用解释器与及时编译器并存的架构。
解释器响应速度快,jit需要翻译时间。互相取长补短。
概念解释:
前端编译器:java文件转变为clss文件,javac、 ecj
后端运行期编译器:jit编译器,c1、c2
静态提前编译器:AOT编译器 ahead of time compiler,gcj、jet
如何选择
热点代码及探测方式
执行的频率高的热点代码,使用jit,深度优化。
一个被多次调用的方法,或者是一个方法体内部循环次数较多的循环体都可以被称之为热点代码。
OSR编译。
方法调用计数器、回编计数器
Client是1500次,Server模式是10000次,超过会触发JIT编译。
阈值可以通过-XX:CompileThreashold
热度衰减
一段时间之内方法被调用的次数,减少一半,衰减,半衰周期
-XX:-UseCounterDecay 关闭热度衰减
-XX:CounterHalfLifeTime设置半衰周期的时间,单位是秒
hotspot虚拟机可以设置程序执行方式
-Xint:完全采用解释器模式执行程序
-Xcomp:完全采用及时编译器模式执行程序。如果及时编译出现问题,解释器会介入执行
-Xmid:采用解释器+及时编译器的混合模式执行程序
hotspot虚拟机中JIT分类:
-client:指定java虚拟机运行在client模式下,并使用c1编译器,会对字节码进行简单可靠的优化,耗时短,以达到更快的编译速度。
-server:指定java虚拟机运行在server模式下,并使用c2编译器,c2会进行耗时较长的优化,以及激进的优化,但是优化的代码执行效率更高。(默认)
写在最后1:
自JDK10起,hotspot加入了Graal编译器。
写在最后2:
AOT编译器,jdk9引入的,编译工具jaotc。