什么是JIT?

1、动态编译(dynamic compilation)指的是“在运行时进行编译”;与之相对的是事前编译(ahead-of-time compilation,简称AOT),也叫静态编译(static compilation)。

2、JIT 编译(just-in-time compilation)狭义来说是当某段代码即将第一次被执行时进行编译,因而叫“即时编译”。JIT编译是动态编译的一种特例。JIT编译一词后来被泛化,时常与动态编译等价;但要注意广义与狭义的JIT编译所指的区别。

3、自适应动态编译(adaptive dynamic compilation)也是一种动态编译,但它通常执行的时机比JIT编译迟,先让程序“以某种式”先运行起来,收集一些信息之后再做动态编译。这样的编译可以更加优化。

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

即时编译器并不是虚拟机必须的部分,Java虚拟机规范并没有规定Java虚拟机内必须要有即时编译器存在,更没有限定或指导即时编译器应该如何去实现。但是,即时编译器编译性能的好坏、代码优化程度的高低却是衡量一款商用虚拟机优秀与否的最关键的指标之一,它也是虚拟机中最核心且最能体现虚拟机技术水平的部分。

由于Java虚拟机规范并没有具体的约束规则去限制即使编译器应该如何实现,所以这部分功能完全是与虚拟机具体实现相关的内容,如无特殊说明,我们提到的编译器、即时编译器都是指Hotspot虚拟机内的即时编译器,虚拟机也是特指HotSpot虚拟机。

为什么HotSpot虚拟机要使用解释器与编译器并存的架构?

尽管并不是所有的Java虚拟机都采用解释器与编译器并存的架构,但许多主流的商用虚拟机(如HotSpot),都同时包含解释器和编译器。

解释器与编译器两者各有优势:当程序需要 迅速启动和执行 的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。在程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取 更高的执行效率 。当程序运行环境中 内存资源限制较大 (如部分嵌入式系统中),可以使用 解释器执行节约内存 ,反之可以使用 编译执行来提升效率 。此外,如果编译后出现“罕见陷阱”,可以通过逆优化退回到解释执行。

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

用Client Complier获取更高的编译速度,用Server Complier 来获取更好的编译质量。为什么提供多个即时编译器与为什么提供多个垃圾收集器类似,都是为了适应不同的应用场景。

编译的时间开销

解释器的执行,抽象的看是这样的:

*输入的代码 -> [ 解释器 解释执行 ] -> 执行结果

而要JIT编译然后再执行的话,抽象的看则是:

*输入的代码 -> [ 编译器 编译 ] -> 编译后的代码 -> [ 执行 ] -> 执行结果

*说JIT比解释快,其实说的是“执行编译后的代码”比“解释器解释执行”要快,并不是说“编译”这个动作比“解释”这个动作快。

JIT编译再怎么快,至少也比解释执行一次略慢一些,而要得到最后的执行结果还得再经过一个“执行编译后的代码”的过程。所以,对“只执行一次”的代码而言,解释执行其实总是比JIT编译执行要快。

怎么算是“只执行一次的代码”呢?粗略说,下面两个条件同时满足时就是严格的“只执行一次”

1、只被调用一次,例如类的构造器(class initializer,())

2、没有循环

对只执行一次的代码做JIT编译再执行,可以说是得不偿失。

对只执行少量次数的代码,JIT编译带来的执行速度的提升也未必能抵消掉最初编译带来的开销。

只有对频繁执行的代码,JIT编译才能保证有正面的收益。

什么是JIT?的更多相关文章

  1. Mono 3.2.7发布,JIT和GC进一步改进

    Mono 3.2.7已经发布,带来了很多新特性,如改进的JIT.新的面向LINQ的解释器以及使用了64位原生指令等等. 这是一次主要特性发布,累积了大约5个月的开发工作.看上去大部分改进都是底层的性能 ...

  2. 谁偷了我的热更新?Mono,JIT,iOS

    前言 由于匹夫本人是做游戏开发工作的,所以平时也会加一些玩家的群.而一些困扰玩家的问题,同样也困扰着我们这些手机游戏开发者.这不最近匹夫看自己加的一些群,常常会有人问为啥这个游戏一更新就要重新下载,而 ...

  3. 谈谈JIT编译器和本机影像生成器(NGen.exe)

    前言 在看<CLR>的时候,作者在开篇的时候提到了NGen.exe,前面一节执行程序集的代码中提到:程序或方法执行前会执行MSCorEE.dll中的JIT函数把要执行方法的IL转换成本地的 ...

  4. .Net JIT

    .Net JIT(转) JIT

  5. 【Java】实战Java虚拟机之五“开启JIT编译”

    今天开始实战Java虚拟机之五“开启JIT编译” 总计有5个系列 实战Java虚拟机之一“堆溢出处理” 实战Java虚拟机之二“虚拟机的工作模式” 实战Java虚拟机之三“G1的新生代GC” 实战Ja ...

  6. 如何控制JVM中的JIT行为?

    首先交代一下我自己的测试环境: Ubuntu 12.04 x86-64,OpenJDK 7 64-bit Server VM(mixed mode) MacOS  10.11,HotSpot  7 6 ...

  7. [llvm] Call the LLVM Jit from c program

    stackoverflow: http://stackoverflow.com/questions/1838304/call-the-llvm-jit-from-c-program Another t ...

  8. JIT动态编译器的原理与实现之Interpreter(解释器)的实现(三)

    接下来,就是要实现一个虚拟机了.记得编码高质量的代码中有一条:不要过早地优化你的代码.所以,也本着循序渐进的原则,我将从实现一个解释器开始,逐步过渡到JIT动态编译器,这样的演化可以使原理看起来更清晰 ...

  9. Android JIT实时编译器的设置

    在Android  JIT实时编译是在Android 2.2之后才引入的,JIT编译器可以显著的提高机器的性能,经过测试,android 2.2的性能较android 2.1提高了 2-5倍.JIT提 ...

  10. .NET学习笔记 -- 那堆名词到底是啥(CLR、CLI、CTS、CLS、IL、JIT)

    什么是CLR? CLR,公共语言运行时(Common Language Runtime)是一个由多种语言使用的“运行时”.他的核心功能包括(内存管理.程序集加载.安全性.异常处理和线程同步),可以被面 ...

随机推荐

  1. Oracle job的用法

    1.Broken()过程更新一个已提交的工作的状态,典型地是用来把一个已破工作标记为未破工作. 这个过程有三个参数:job .broken与next_date. PROCEDURE Broken (j ...

  2. 如何在印刷品中使用遵循SIL Open Font License协议的字体

    如何在印刷品中使用遵循SIL Open Font License协议的字体 昨天在知乎看到了一个问题,( 如何在设计中声明字体开源许可证? - 知乎 (zhihu.com),恰好最近在研究一些开源协议 ...

  3. docker内服务访问宿主机服务

    目录 1. 场景 2. 解决 4. 参考 1. 场景 使用windows, wsl2 进行日常开发测试工作. 但是wsl2经常会遇到网络问题.比如今天在测试一个项目,核心功能是将postgres 的数 ...

  4. Spring Cloud Alibaba 使用Nacos作为服务注册中心

    为什么需要注册中心? 在分布式架构中,服务会注册到这里,当服务需要调用其它服务时,就到这里找到服务的地址,进行调用:服务管理,核心是有个服务注册表,心跳机制动态维护 : 服务注册 创建普通Spring ...

  5. numpy.zeros()的作用和实操

    numpy.zeros()的作用: 通常是把数组转换成想要的矩阵 numpy.zeros()的使用方法: zeros(shape, dtype=float, order='C') shape:数据尺寸 ...

  6. 攻防世界 web4.cookie

    题有几种解法,我有点懒,懒的打开burp,所以可以直接在浏览器拿flag, 首先访问ip/cookie.php,提示:See the http response 接着F12查看响应头 给你cyberp ...

  7. Verilog设计技巧实例及实现

    Verilog设计技巧实例及实现 1 引言 最近在刷HDLBits的过程中学习了一些Verilog的设计技巧,在这里予以整理.部分操作可能降低代码的可读性和Debug的难度,请大家根据实际情况进行使用 ...

  8. Linux 显示ip、dns、网关等命令

    在新版的ubuntu 终端里输入命令nm-tool, 想查看网络参数设置, 没想到却返回如下内容:   未找到 'nm-tool' 命令,您要输入的是否是:  命令 'dm-tool' 来自于包 'l ...

  9. linux 内核源代码情景分析——linux 内存管理的基本框架

    386 CPU中的页式存管的基本思路是:通过页面目录和页面表分两个层次实现从线性地址到物理地址的映射.这种映射模式在大多数情况下可以节省页面表所占用的空间.因为大多数进程不会用到整个虚存空间,在虚存空 ...

  10. Oracle创建表、删除表、修改表、字段增删改 语句总结

    创建表: create table 表名 ( 字段名1 字段类型 默认值 是否为空 , 字段名2 字段类型 默认值 是否为空, 字段名3 字段类型 默认值 是否为空, ...... ); 创建一个us ...