JVM之JIT即时编译
Posted Coding的哔哔叨叨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM之JIT即时编译相关的知识,希望对你有一定的参考价值。
当今Java语言被广为接受的优点之一就有即时编译,即时编译的存在使得Java应用可以运行时间的增长而获得更高的性能。
JIT(just-in-time)
Coding的哔哔叨叨
很显然,解释执行,其执行速度必然会比可执行的二进制字节码程序慢很多,为了提高执行速度,引入了即时编译技术。
Java程序最初是通过解释器(interpreter)进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁,就会把这些代码认为是“热点代码”。为了提高热点代码的执行效率,在运行时,虚拟机会把这些代码编译成与本地机器相关的机器码,并进行各种层次的优化,完成这个任务的编译器称之为“即时编译器(just-in-time compiler)”。
注意:即时编译器并不是java虚拟机的必须部分,java虚拟机规范并没有规定必须要有即时编译器的存在,并且,更没有要求或指导如何实现即时编译器;但是即时编译器的好坏、代码优化程度高低却是衡量一款商用虚拟机的重要指标之一,它也是虚拟机最核心且最能体现虚拟机技术水平的的部分。
由于上述原因,所以即时编译器完全是某虚拟机具体实现的相关内容,所以,如无特殊说明,本文所提到的即时编译器都是Hotspot虚拟机内的即时编译器;所提到的虚拟机也是专门特指Hotspot虚拟机。
JVM运行原理
Coding的哔哔叨叨
为什么Hotspot要使用解释器与编译器并存的架构?
Coding的哔哔叨叨
编译的时间开销
Coding的哔哔叨叨
解释器:输入代码->[解释器解释执行]->执行结果
编译器:输入代码->[编译器编译]->编译后的代码->执行结果。
方法被多次调用,相反类似类构造器(class initializer,<clinit>())只被调用一次。
存在循环。
编译的空间开销
Coding的哔哔叨叨
对java语言来说,编译后的代码相对于class字节码,膨胀达10倍是很正常的,同上面所说的时间开销一样,只有针对频繁执行的代码,才能保证有正向收益,才值得去编译,如果把所有的代码都进行编译,会很明显的增加代码所占空间。
JIT编译,会将编译后的汇编指令保存在代码缓存中,代码缓存是固定大小的,当jvm代码缓存一旦被填满,jvm就不能编译更多的代码。
所以,这也解释了,为什么虚拟机不完全采用JIT编译执行,而是选择解释器与编译器混合共存的执行引擎。
现在并没有一个好的机制可以确定一个特定的应用到底需要多大的代码缓存。因此,当需要提高代码缓存时,这将是一种凑巧的操作,一个通常的做法是将代码缓存变成默认大小的两倍或四倍。
可以通过 –XX:ReservedCodeCacheSize=Nflag(N 就是之前提到的默认大小)来最大化代码缓存大小。代码缓存的管理类似于 JVM 中的内存管理:有一个初始大小(用-XX:InitialCodeCacheSize=N 来声明)。代码缓存的大小从初始大小开始,随着缓存被填满而逐渐扩大。代码缓存的初始大小是基于芯片架构(例如 Intel 系列机器,client 编译器模式下代码缓存大小起始于 160KB,server 编译器模式下代码缓存大小则起始于 2496KB)以及使用的编译器的。重定义代码缓存的大小并不会真正影响性能,所以设置 ReservedCodeCacheSize 的大小一般是必要的。
再者,如果 JVM 是 32 位的,那么运行过程大小不能超过 4GB。这包括了 Java 堆,JVM 自身所有的代码空间(包括其本身的库和线程栈),应用程序分配的任何的本地内存,当然还有代码缓存。
所以说代码缓存并不是无限的,很多时候需要为大型应用程序来调优(或者甚至是使用分层编译的中型应用程序)。比如 64 位机器,为代码缓存设置一个很大的值并不会对应用程序本身造成影响,应用程序并不会内存溢出,这些额外的内存预定一般都是被操作系统所接受的。
Hotspot的两个不同编译器
Coding的哔哔叨叨
哪些代码会被即时编译?
Coding的哔哔叨叨
被多次调用的方法。
被多次执行的循环体。
注意:上面两种情况,编译器都是以整个方法作为编译对象,编译方法发生在方法执行过程中,我们称之为:栈上替换(OSR,On Stack Replacement),方法栈针还在栈上,方法就被替换了。
如何编译为本地代码?
Coding的哔哔叨叨
HotSpot的热点探测技术
Coding的哔哔叨叨
基于采样的热点探测
基于计数器的热点探测
方法调用计数器
回边计数器
它的作用就是统计一个方法中循环体代码执行的次数,在字节码中遇到控制流向后跳转的指令称为“回边”。
文章部分图片来源于网络其他优秀工程师的分享。
javac编译与JIT编译
Coding的哔哔叨叨
不积跬步,无以至千里。
文章有帮助的话,点个转发、在看呗。
谢谢支持哟 (*^__^*)
END
以上是关于JVM之JIT即时编译的主要内容,如果未能解决你的问题,请参考以下文章