2019-01-12 初识JVM

2019-01-13  本文已影响0人  孟圆的笔记

JIT编译器是“动态编译器”的一种,相对的“静态编译器”则是指的比如:C/C++的编译器。

JIT并不是JVM的必须部分,JVM规范并没有规定JIT必须存在,更没有限定和指导JIT。但是,JIT性能的好坏、代码优化程度的高低却是衡量一款JVM是否优秀的最关键指标之一,也是虚拟机中最核心且最能体现虚拟机技术水平的部分。

编译器与解释器

主流商用虚拟机,都同时包含这两部分。

配合过程

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

 

解释器 - Interpreter

Interpreter解释执行class文件,好像JavaScript执行引擎一样。

特殊的例子:

  • 最早的Sun Classic VM只有Interpreter。
  • BEA JRockit VM则只有Compiler,但它主要面向服务端应用,部署在其上的应用不重点关注启动时间。

 

编译器 - Compiler

只说HotSpot JVM

  1. C1和C2:
    HotSpot虚拟机内置了两个即时编译器,分别称为Client Compiler和Server Compiler,习惯上将前者称为C1,后者称为C2。

  2. 使用C1还是C2?
    HotSpot默认采用解释器和其中一个编译器配合的方式工作,使用哪个编译器取决于虚拟机运行的模式,HotSpot会根据自身版本和宿主机器硬件性能自动选择模式,用户也可以使用“-client”或”-server”参数去指定。

$ java -version
java version "1.8.0_51"
Java(TM) SE Runtime Environment (build 1.8.0_51-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.51-b03, `mixed mode`)

在JDK1.7(1.7仅包括Server模式)之后,HotSpot就不是默认“采用解释器和其中一个编译器”配合的方式了,而是采用了分层编译,分层编译时 C1和C2有可能同时工作

分层编译(Tiered Compilation)

由于编译器compile本地代码需要占用程序时间,要编译出优化程度更高的代码所花费的时间可能更长,且此时解释器还要替编译器收集性能监控信息,这对解释执行的速度也有影响。

所以,为了在程序启动响应时间与运行效率之间达到最佳平衡,HotSpot在JDK1.6中出现了分层编译(Tiered Compilation)的概念并在JDK1.7的Server模式JVM中作为默认策略被开启。

编译层(tier) / 编译级别
分层编译根据编译器编译、优化的规模与耗时,划分了不同的编译层次(不只以下3种),包括:

实施分层编译后,C1和C2将会同时工作,许多代码会被多次编译,用C1获取更高的编译速度,用C2来获取更好的编译质量,且在解释执行的时候解释器也无须再承担收集性能监控信息的任务。

 

编译对象与触发条件

1. 谁被编译了?
编译对象就是之前说的“热点代码”,它有两类:

2. 触发条件:

 

编译过程

编译过程是在后台线程(daemon)中完成的,可以通过参数“-XX:-BackgroundCompilation”来禁止后台编译,但此时执行线程就会同步等待编译完成才会执行程序。

使用参数“-XX:+PrintCompilation”会让虚拟机在JIT时把方法名称打印出来,如图:

 

Java和C/C++的编译器对比

这里不是比Java和C/C++谁快这种大坑问题,只是比较编译器(我认为开发效率上Java快,执行效率上C/C++快)
这种对比代表了经典的即时编译器静态编译器的对比,其实总体来说Java编译器有优有劣。主要就是动态编译时间压力大能做的优化少,还要做一些动态校验。而静态编译器无法实现一些开发上很有用的动态特性。

上一篇 下一篇

猜你喜欢

热点阅读