JVM编译过程理解

JVM编译过程理解

前言

不知道大家有没有注意,jdk分为linux版和windows版,java 之所以能够跨平台也是因为这个,不同的运行环境(linux,windows)我们需要安装对应的jdk。我们知道javac是编译命令,会把.java文件编译成.class文件,这时我们用命令java 即可运行编译后的.class文件。我们删掉.java文件也是可以运行的,说明java程序的运行不依赖于.java文件,仅仅与.class文件有关。我们把这个class文件放到linux服务器上用命令java运行效果和在windows上一样。这个就是java的跨平台性。当然这些与我要谈的东西没有关系,红红火火恍恍惚惚。

正文

我们知道Java是解释执行的一门语言,不像C语言,直接编译成平台机器码执行,所以我们说Java效率没有c语言快也是有道理的,毕竟Java代码要运行首先要编译成class文件,jvm才能够识别,然后加以解释(也就是编译成机器码直接运行出结果,没有中间物生成,编译后的机器码不会保存)产出我们想要的结果。
class文件最初仅仅通过解释器解释执行的,即对字节码逐条解释执行,很容易发现问题,这种方式的执行速度相对会比较慢,尤其当某个方法或代码块运行的特别频繁时,这种方式的执行效率就会很低。于是后来在虚拟机中引入了 JIT 编译器(即时编译器),当虚拟机发现某个方法或代码块运行特别频繁时,就会把这些代码认定为**“Hot Spot Code”(热点代码)**,为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各层次的优化,完成这项任务的正是 JIT 编译器。我们说的仅仅是热点代码被JIT编译,为什么呢,两个方面,我们看一张图
此图来自于别人的博客
可以看出JIT编译执行是比解释器执行多两个环节的,也就是编译执行的过程更加耗时;另一方面,编译之后的机器码是存在于内存中,也就是需要占用更多的内存
就会有人问不是说JIT编译是为了提高执行效率吗为什么还更加耗时了,因为编译之后的机器码是保存下来了,保存在内存中,下一次执行就不再需要经过class编译成机器码的过程了,可以直接执行机器码,节省时间也就是这一点。

jvm是虚拟机规范,它不是一个具体的虚拟机,基于这个规范的产品HotSpot(sun公司的),因为绝大部分我们都用的是sun公司的jdk,后面说的都是HotSpot

HotSpot内置了两个JIT编译器,Client Complier 和 Server Complier,分别用在客户端和服务端,目前主流的 HotSpot 虚拟机中默认是采用解释器与其中一个编译器直接配合的方式工作。
在这里插入图片描述
建议服务器上启用server编译器

上面我们说热点代码才会被JIT编译器编译,那么什么样的代码才是热点代码呢,目前热点判定的方法有两个

  • 基于采样的热点探测:采用这种方法的虚拟机会周期性地检查各个线程的栈顶,如果发现某些方法经常出现在栈顶,那这段方法代码就是“热点代码”。这种探测方法的好处是实现简单高效,还可以很容易地获取方法调用关系,缺点是很难精确地确认一个方法的热度,容易因为受到线程阻塞或别的外界因素的影响而扰乱热点探测。
  • 基于计数器的热点探测:采用这种方法的虚拟机会为每个方法,甚至是代码块建立计数器,统计方法的执行次数,如果执行次数超过一定的阀值,就认为它是“热点方法”。这种统计方法实现复杂一些,需要为每个方法建立并维护计数器,而且不能直接获取到方法的调用关系,但是它的统计结果相对更加精确严谨。

在 HotSpot 虚拟机中使用的是第二种——基于计数器的热点探测方法,因此它为每个方法准备了两个计数器:方法调用计数器回边计数器
方法计数器统计的不是方法被调用的绝对次数,而是一个频率值(规定时间内方法被调用的次数)
回边计数器用于统计一个方法中循环体代码执行的次数(准确地说,应该是回边的次数,因为并非所有的循环都是回边),在字节码中遇到控制流向后跳转的指令就称为“回边”。

在确定虚拟机运行参数的前提下,这两个计数器都有一个确定的阀值,当计数器的值超过了阀值,就会触发JIT编译。触发了 JIT 编译后,在默认设置下,执行引擎并不会同步等待编译请求完成,而是继续进入解释器按照解释方式执行字节码,直到提交的请求被编译器编译完成为止(编译工作在后台线程中进行)。当编译工作完成后,下一次调用该方法或代码时,就会使用已编译的版本。

参考
http://wiki.jikexueyuan.com/project/java-vm/javac-jit.html
https://cloud.tencent.com/developer/article/1189433
https://blog.csdn.net/sunxianghuang/article/details/52094859

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值