什么是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. pg_basebackup报错: pg_basebackup: incompatible server version 12.4

    pg_basebackup报错 今日从库复制主库data时,发现pg_basebackup无法使用,详情如下: 错误为:incompatible server version 12.4 [postgr ...

  2. 分布式系统ID

    Leaf--美团点评分布式ID生成系统 前言 在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识.如在美团点评的金融.支付.餐饮.酒店.猫眼电影等产品的系统中,数据日渐增长,对数据分库分表后需 ...

  3. BUAA 2020 软件工程 提问回顾与个人总结

    BUAA 2020 软件工程 提问回顾与个人总结 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 提问回顾 ...

  4. Vue 报错Error in render: “TypeError: Cannot read properties of null (reading ‘xxx’)” found in

    前端vue报错 [Vue warn]: Error in render: "TypeError: Cannot read properties of null (reading 'name' ...

  5. Noip模拟8 2021.6.17

    T1 星际旅行 仔细一看,发现像一个欧拉路(简称一笔画). 满足"可以一笔画"的条件是: 1.所有点都有偶数条连边; 2.有偶数个点连奇数条边; 满足以上两个条件的任意一个即可一笔 ...

  6. Redis的浅入门

    Redis的浅入门 # 缓存的思想 问题提出:我们的用户数量上亿,如果登录,访问数据库user特别耗时,该怎么办?--提出缓存 方法:怎样从缓存在获取数据? *有数据: 直接返回 *无数据: (1)从 ...

  7. Spring中自定义Schema扩展机制

    一.前言 Spring 为基于 XML 构建的应用提供了一种扩展机制,用于定义和配置 Bean. 它允许使用者编写自定义的 XML bean 解析器,并将解析器本身以及最终定义的 Bean 集成到 S ...

  8. sort命令的学习与实践

    一.用man sort 查看sort的帮助文档 *sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出. [rocrocket@ro ...

  9. JAVA笔记4__static关键字/对象数组/foreach/方法的可变参数

    /** * static关键字:修饰属性(实质就是全局变量).方法(无需本类的对象即可调用此方法).类. * 1.static方法只能调用static方法 * 2.static方法只能访问static ...

  10. 一步一步学ROP之linux_x64篇(蒸米spark)

    目录 一步一步学ROP之linux_x64篇(蒸米spark) 0x00 序 0x01 Memory Leak & DynELF - 在不获取目标libc.so的情况下进行ROP攻击 0x02 ...