执行引擎是java虚拟机的核心部分之一
物理机的执行引擎是直接建立在处理器、缓存、指令集和操作系统上的,虚拟机的执行引擎则是由软件自行实现的。所以可以不受物理条件制约,来定制指令集与执行引擎的结构,能够执行不被硬件直接支持的指令集,但是效率是不如物理机的
jvm的主要任务就是加载字节码文件,但是字节码并不能直接运行在操作系统,所以就需要执行引擎把字节码指令解释、编译为对应平台的本地机器指令,简单来说,执行引擎就是把高级语言翻译为机器语言的翻译官
大部分程序代码都需要经历上面的过程
生成字节码文件的过程称为前端编译,把字节码文件编译成机器指令称为后端编译
上图黄色是生成字节码文件的过程
绿色部分是解释的过程
蓝色部分是编译的过程
java是半编译半解释的语言,就是执行引擎在执行时,既可以使用编译器执行,又可以使用解释器执行
java在1.0时,只有解释执行,后来才引入的编译器,现在通常都是二者结合起来使用
对于硬件来说,只认识机器指令,高级语言也必须翻译为汇编,然后在翻译为机器指令,高级语言不能直接翻译为机器语言
如果只是为了跨平台,那么直接把代码翻译成汇编语言,再把汇编语言翻译为机器指令也是可以实现跨平台,但是这样对虚拟机的要求会非常高,而引入字节码文件,可以降低虚拟机的要求,还能防止源代码泄露,而且字节码可以跨语言
解释器其实就是一个 翻译者 的角色,将字节码文件的内容翻译为对应平台的机器指令,当一条字节码指令被解释执行完成以后,接着在根据pc寄存器中记录的下一条需要被执行的字节码指令执行解释操作
解释器是很多语言中都存在的,但是解释器的效率通常较低
为了解决这个问题,jvm支持了即时编译技术,目的是避免函数被解释执行,而是将整个函数体编译为机器码,每次函数执行时,只执行编译后的机器码即可,这种及时编译技术大幅度提高了执行效率
JIT编译器是hotspot执行的一种方式。
hotspot在虚拟机启动时,解释器首先发挥作用,不必等到即时编译器全部编译完成在执行,这样可以省去很多不必要的等待时间,并且随着程序运行时间的推移,即时编译器逐渐发挥作用,根据热点探测功能把有价值的字节码编译为本地机器指令,以换取更高的执行效率,另外解释器还可以作为备选方案
而 JRockit 就没有解释器,所以启动时间会很长,但是执行效率更高,因为对于服务器端来说,启动时间并不重要
是否需要使用 jit编译器把字节码编译为对应平台的本地机器指令,需要根据代码被调用的执行频率决定,频率高的代码就叫做热点代码,对于热点代码就可以做出深度优化,将其直接编译为机器指令,提升java程序的执行性能
这种编译方式发生在执行过程中,所以被称为栈上替换,简称为: OSR
hotspot所采用的是基于计数器的热点探测,目前计数器有下面两个
方法调用计数器:
hotspot 可以手动程序设置执行方式,默认是混合模式
hotspot虚拟机内嵌了两个jit编译器:Client Complier、Server Complier ,简称为c1 、c2
c1、c2编译器的优化策略:
c1主要有:方法内联、去虚拟化、冗余消除
c2优化为:在逃逸分析的基础上,变量替换、栈上分配、同步消除
在jdk1.7之后,c1 、c2 是可以相互协同使用的
jit是在程序运行过程中执行的,aot是提前编译器(jdk9引入的),在程序执行之前进行一些优化,可减少java给人第一次运行起来慢的印象
但是缺点是字节码文件就不能跨平台了(生成的机器指令不跨平台),降低了java链接过程的动态性,且目前只支持64位的linux