JVM-HotSpot虚拟机-即时编译器、编译优化


JIT简介
JIT(just in time)编译器,也就是即时编译器(它把字节码转换为可执行的机器码),能够 加速java程序的执行速度

为什么JIT编译器能够加速java程序的执行速度呢?
首先我们要知道,通常javac将程序源代码编译,转换成 java字节码(.java文件编译转换成.class文件,这也是我们通常意义上所理解的编译)。但是字节码不是机器语言,想要让机器执行,还需要通过JVM来解释字节码,将其翻译成对应的 机器指令,逐条读入,逐条解释翻译(这个过程也叫编译,更深层次的编译)。但是通过解释执行,它的执行效率必定会比可执行的二进制字节码程序慢很多(这就是传统的 JVM解释器Interpreter的功能)。为了提高速度,引入了JIT技术,JIT会把JVM认为是“ 热点代码”(运行特别频繁的某个方法,或者代码块)的部分代码,翻译成目标机器相关的 机器码并优化,然后 缓存起来,已备下次使用。

热点检测
目前主要出 热点代码识别的方式就是 热点检测,热点检测有以下两种方式:
  1. 基于采样方式的热点探测:
周期性的检查各个线程的栈顶,如果某个方法经常出现在栈顶,就认为它是热点方法。优点的是简单,缺点是无法精确确认一个方法的热度,容易受线程阻塞,或别的原因干扰检测点。
  1. 基于计数器的热点探测:
虚拟机会为每个方法,甚至代码块创建计数器,统计方法的执行次数,某个方法超过阈值就认为是热点方法。触发JIT编译。HotSpot就是用的这种方法,它为每个方法准备了两个计数器:
方法调用计数器:记录一个方法被调用次数的计数器。
回边计数器:记录方法中的for或者while的运行次数的计数器。

编译优化
HotSpot虚拟机中内置了两个JIT编译器: Client ComplierServer Complier,分别用在客户端和服务端,通过 java -version 命令,就可以看到自己的JIT属于哪种:

上图用的,就是Server Complier,目前主流的是HotSpot虚拟机中,默认的是采用一个解释器和其中一个JIT编译器直接配合工作,就是上图的mixed mode。
  1. 客户端或C1编译器,它的编译临界值比较低,只是1500,这有助于减少启动时间。
  2. 服务端或C2编译器,它的编译临界值比较高,达到了10000(启动速度会慢,但运行起来后,效率比C1高),这有助于针对性能关键的方法生成高度优化的代码,这些方法由应用的关键执行路径来判定是否属于性能关键方法。

代码缓存
JIT缓存是有固定大小的,一旦它被填满,JVM就不能编译更多代码,这样有些热点代码会被编译,其他则不会被编译。这时候就可以通过 –XX:ReservedCodeCacheSize=Nflag(N 就是之前提到的默认大小)来最大化代码缓存大小。


参考资料:《HotSpot实战》

猜你喜欢

转载自blog.csdn.net/qq_26807245/article/details/80841051