笔记-Java基础之Hotspot虚拟机解释器与编译器

   在部分的商用虚拟机(Sun HotSpot、IBM J9)中,Java程序最初是通过解释器(Interpreter)进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这个代码认定为"热点代码",为了提高热点代码的执行,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(Just In Time Compiler,下文中简称JIT编译器)

解释器与编译器

    解释器与编译器两者各有优势:当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。在程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。当程序发现运行环境中内存资源限制较大(如部分嵌入式系统中),可以使用解释执行节约内存,反之可以使用编译执行来提升效率。同时,解释器还可以作为编译器激进优化时的一个“逃生门”,让编译器根据概率选择一些大多数时候都能提升运行速度的优化手段,当激进优化的假设不成立,如加载了新类后类型继承结构出现变化、出现“罕见陷阱”(Uncommon Trap)时可以通过逆优化(Deoptimization)退回到解释状态继续执行(部分没有解释器的虚拟机中也会采用不进行激进优化的C1编译器担当“逃生门”的角色),因此,在整个虚拟机执行架构中,解释器与编译器经常配合工作如下图所示:

笔记-Java基础之Hotspot虚拟机解释器与编译器_第1张图片

    HotSpot虚拟机中内置了两个即时编译器,分别称为Client CompilerServer Compiler,或者简称为C1编译器C2编译器(也叫Opto编译器)。目前主流的HotSpot虚拟机(Sun系列JDK1.7及之前版本的虚拟机)中,默认采用解释器与其中一个编译器直接配合的方式工作,程序使用哪个编译器,取决于虚拟机运行的模式,HotSpot虚拟机会根据自身版本与宿主机器的硬件性能自动选择运作模式,用户也可以使用“-client”和“-server”参数去强制指定虚拟机运行在Client模式或Server模式。

    无论采用的编译器是Client Compiler还是Server Compiler,解释器与编译器搭配使用的方式在虚拟机中称为“混合模式”(Mixed Mode),用户可以使用参数“-Xint”强制虚拟机运行于“解释模型”(Interpreted Mode),这时编译器完全不介入工作,全部代码都使用解释方式执行。也可以使用参数"-Xcomp"强制虚拟机运行于"编译模式"(Compiled Mode),这时将优先采用编译方式执行程序,但是解释器仍然要在编译无法进行的情况下介入执行过程,可以通过虚拟机"-version"命令的输入结果显示出这三种模式。

笔记-Java基础之Hotspot虚拟机解释器与编译器_第2张图片

    由于编译器编译本地代码需要占用程序运行时间,要编译出优化程度更高的代码,所花费的时间可能更长:而且想要编译出优化程度更高的代码,解释器可能要替编译器收集性能监控信息,这对解释执行的速度也有影响。为了程序启动响应速度与运行效率之间达到最佳平衡,HotSport虚拟机还会逐渐启用分层编译(Tiered Compilation)的策略,分层编译的概念在JDK1.6时期出现,最终在JDK1.7的Server模式虚拟机中作为默认编译策略被开启。分层编译根据编译器编译、优化的规模与耗时,划分出不同的编译层次,其中包括

第0层:程序解释执行,解释器不开启性能监控功能(Profiling),可触发第1层编译。

第1层:也称为C1编译,将字节码编译为本地代码,进行简单,可靠的优化,如有必要将加入性能监控的逻辑。

第2层(或2层以上):也称为C2编译,也是将字节码编译为本地代码,但是会启用一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。

    实施分层编译后,Client Compiler和Server Compiler将会同时工作,许多代码都可能会被多次编译,用Client Compiler获取更高的编译速度,用Server Compiler来获取更好的编译质量,在解释执行的时候也无须再承担收集性能监控的任务。如有必要,会加入性能监控的逻辑。

你可能感兴趣的:(jvm,虚拟机,编译器,解释器,java)