部分内容来自以下博客:
https://www.cnblogs.com/old-cha/p/13324772.html
1 概述
先看一下Java虚拟机的结构图:
从图中可以看到,当类加载器将class文件的数据放到运行时数据区后,虚拟机就使用执行引擎读取代码并执行。
由于Java代码中有可能用到了本地化的方法,所以执行引擎还需要调用本地化方法库中相应的本地化接口。
2 执行引擎
2.1 作用
执行引擎的任务就是将字节码指令解释/编译为对应平台上的本地机器指令。
从外观上看,所有的Java虚拟机的执行引擎输入、输出都是一致的:输入的是字节码的二进制流,处理过程是字节码解析执行的等效过程,输出的是执行结果。
2.2 分类
2.2.1 解释和编译
第一种是将源代码编译成字节码文件,然后在运行时通过解释器将字节码转为机器码执行
第二种是编译执行(直接编译成机器码)。现代虚拟机为了提高执行效率,会采用即时编译技术(Just In Time)将方法编译成机器码后再执行。
2.2.2 两者同时使用的原因
为什么HotSpot中已经内置JIT(Just In Time Compiler)编译器,还需要使用解释器拖累程序性能?
1)当Java虚拟机启动时,解释器可以先发挥作用,而不必等待即时编译器全部编译完成后再执行,这样可以省去许多不必要的编译时间。
2)随着时间的推移,编译器发挥作用,把越来越多的代码编译成本地机器码,获得更高的执行效率。
3)同时,解释执行在编译期进行激进优化不成立时,作为后备方案。
2.3 解释器
2.3.1 作用
当Java虚拟机启动时会对字节码采用逐行解释的方式执行,将每条字节码文件中的内容“翻译”为对应平台的本地机器指令执行。
当一条字节码指令被解释执行完成后,接着再根据PC寄存器中记录的下一条需要被执行的字节码指令执行解释操作。
2.3.2 种类
在Java的发展历史里,一共有两套解释执行器,即古老的字节码解释器、现在普遍使用的模板解释器。
字节码解释器在执行时通过纯软件代码模拟字节码的执行,效率非常低下。
模板解释器将每一条字节码和一个模板函数关联,模板函数中直接产生这条字节码执行时的机器码,从而很大程度上提高了解释器的性能。
2.3.3 组成
在HotSpot VM中,解释器主要由Interceptor模块和Code模块构成。
Interceptor模块:实现了解释器的核心功能。
Code模块:用于管理HotSpot VM在运行时生成的本地机器指令。
2.4 编译器
2.4.1 作用
编译器就是虚拟机将源代码直接编译成本地机器平台相关的机器语言。
2.4.2 即时编译
即时编译的目的是避免函数被解释执行,而是将整个函数体编译为机器码,每次函数执行时,只执行编译后的机器码即可。
2.4.3 热点代码
是否需要启动JIT编译器将字节码直接编译为对应平台的本地机器指令,需要根据代码被调用执行的频率而定。
JIT编译器在运行时会针对频繁被调用的热点代码进行深度优化,将其直接编译为对应平台的本地机器指令,从而提升Java程序的执行性能。
3 本地接口
JNI会与本地方法库进行交互并提供执行引擎所需的本地库。
4 本地方法库
是一个执行引擎所需的本地库的集合。