即时编译回顾

HotSpot 虚拟机执行 Java 程序时,先通过解释器对代码解释执行,发现某个方法或代码块执行比较频繁后,对热点代码进行编译,编译后生成与本地平台相关的机器码,再去执行机器码获得较高的运行效率。必要时,也会通过逆优化从即时编译回到解释执行,如编译器遇到罕见陷阱的情况。

在 Java 虚拟机规范中,并未要求虚拟机必须实现即时编译,但即时编译在主流的虚拟机中都有实现,后文所有讨论都基于 HotSpot 虚拟机。

即时编译器

HotSpot 虚拟机中有两个即时编译器,分别为 Client Compiler 和 Server Compiler,简称为 C1 编译器和 C2 编译器。C1 编译器占用内存小,进行局部优化,代码执行效率比 C2 编译器低,适用于客户端应用; C2 编译器占用内存大,进行全局优化,代码执行效率比 C1 编译器高,适用于服务端应用。在 JDK 1.7 以后的 HotSpot 虚拟机中,采用了被称为分层编译的策略,启动时解释执行提高启动速度,然后 C1 编译获取较好的编译速度,再 C2 编译获取较好的编译质量。

默认情况下,虚拟机会自动选择合适的编译器与解释器一起配合工作,用户也可以在启动参数里使用 “-client” 或 “-server” 来强制要求虚拟机使用某一种编译器。编译器与解释器一起配合工作的模式,被称为混合模式。用户也可以在启动参数里使用 “-Xint” 来要求虚拟机只使用解释器,使用 “-Xcomp” 来要求虚拟机只使用编译器。

被多次调用的方法和被多次执行的循环体,就是即时编译器关注的热点代码。在 HotSpot 中,采用了基于计数器的热点探测技术,为每个方法定义了两个计数器:方法调用计数器、回边计数器。

默认情况下,如果一段时间内方法调用计数器的值没有超过虚拟机设置的阈值,则在垃圾回收时计数器会热度衰减,数值减少 1/2,此时间范围又被称为半衰期。所以方法调用计数器中存储的实际上并不是方法调用的绝对次数。用户可以调整半衰期的值,甚至可以关闭热度衰减。

回边计数器则统计了循环体执行的绝对次数,它的阈值可以由方法调用计数器的阈值计算出来。如果回边计数器发生溢出,也会把方法调用计数器调整为溢出。

调用方法时,如果两个计数器之和超过了方法调用计数器的阈值,就会提交方法的编译请求。循环体执行时,如果两个计数器之和超过了回边计数器的阈值,也是编译代码块所在的方法,因为此时方法正在执行中,又被称为栈上替换,即替换方法时方法的栈帧还在栈上。

默认情况下,编译器在后台进行编译,即调用热点代码发现需要编译时,先以解释方式继续执行,向编译器发送编译请求,编译结束后下次调用时才使用编译的本地代码。用户也可以通过启动参数来要求虚拟机禁止后台编译,编译结束前热点代码的执行处于阻塞状态。

优化技术

HotSpot 虚拟机使用了很多种优化技术,这里只简单介绍其中的几种,完整的优化技术介绍可以参考官网内容。

公共子表达式消除:

如果一个表达式已经进行过计算,并且在下次用到之前依赖的变量没有变化,即表达式的计算结果不会发生变化,则在下次使用这个表达式时直接使用计算的结果。

数组边界检查消除:

在 Java 中访问数组时,会自动进行边界检查来防止数组下标越界。但是对于某些情况并不需要每次访问都去检查,如在一个循环中遍历数组元素,如果虚拟机能够确定下标不会发生越界并且优化确实能够提高运行速度,则虚拟机会去除每次访问的下标检查。

方法内联:

对于可以内联的方法,直接复制到调用者代码中,减少方法调用次数和性能消耗。

逃逸分析:

方法中定义的一个对象,如果会被其他方法访问则称为方法逃逸,如果会被其他线程访问则称为线程逃逸。对于不能逃逸的对象,HotSpot 虚拟机采用了栈上分配、同步消除、标量替换等方法进行优化。

每周 3 篇学习笔记或技术总结,面向有一定基础的 Java 程序员,内容涉及 Java 进阶、虚拟机、MySQL、NoSQL、分布式计算、开源框架等多个领域。关注作者或微信公众号 backend-develop 第一时间获取最新内容。

浅析 JIT 即时编译技术 | 后端开发那点事儿

浅析 JIT 即时编译技术的更多相关文章

  1. java 笔记(1)-—— JVM基础,内存数据,内存释放,垃圾回收,即时编译技术JIT,高精度类型

    1.java中5个存放数据的地方: (1).寄存器(Registers):位于CPU内部,是速度最快的存储区,但是数量和容量有限.在java中不能直接操作寄存器. (2).栈(Stack):栈位于通用 ...

  2. JIT——即时编译的原理

     介绍 java 作为静态语言十分特殊,他需要编译,但并不是在执行之前就编译为本地机器码. 所以,在谈到 java的编译机制的时候,其实应该按时期,分为两个部分.一个是 javac指令 将java源码 ...

  3. 为什么 JVM 不用 JIT 全程编译?

    考虑到跨平台,所以无法使用AOT: 考虑到执行效率,所以无法全部使用JIT: 编译技术大约分为两种,一种AOT,只线下(offline)就将源代码编译成目标机器码,这是普遍用在系统程序语言中:另一种是 ...

  4. JIT(动态编译)和AOT(静态编译)编译技术比较

    Java 应用程序的性能经常成为开发社区中的讨论热点.因为该语言的设计初衷是使用解释的方式支持应用程序的可移植性目标,早期 Java 运行时所提供的性能级别远低于 C 和 C++ 之类的编译语言.尽管 ...

  5. 即时编译(JIT)

    即时编译(JIT : just-in-time compilation): 指计算机领域里,即时编译也被成为动态翻译,是一种通过在运行时将字节码翻译为机器码,从而改善字节码编译语言性能的技术 即时编译 ...

  6. JVM即时编译(JIT)

    Java解释执行过程: 代码装入-代码校验-代码执行 Java字节码的执行方式分为两种:即使编译方式和解释执行方式.即时编译是值解释器先将字节码编译成机器码,然后执行该机器码.解释执行的方式是指解释器 ...

  7. Java 面试-即时编译( JIT )

    当我们在写代码时,一个方法内部的行数自然是越少越好,这样逻辑清晰.方便阅读,其实好处远不止如此,通过即时编译,甚至可以提高执行时的性能,今天就让我们好好来了解一下其中的原理. 简介 当 JVM 的初始 ...

  8. 转:什么是即时编译(JIT)!?OpenJDK HotSpot VM剖析

    重点 应用程序可以选择一个适当的即时编译器来进行接近机器级的性能优化. 分层编译由五层编译构成. 分层编译提供了极好的启动性能,并指导编译的下一层编译器提供高性能优化. 提供即时编译相关诊断信息的JV ...

  9. JIT(Just in time,即时编译,边运行边编译)、AOT(Ahead Of Time,运行前编译),是两种程序的编译方式

    JIT(Just in time,即时编译,边运行边编译).AOT(Ahead Of Time,运行前编译),是两种程序的编译方式

随机推荐

  1. Python-面向网络编程-socket原理

    socket 整个计算机网络是由协议构成,想要通信必须遵守对应的协议,如Web中的http协议.传输协议TCP和UDP等等.在网络工程师的眼中,可能现在网络上的一切都是socket,一切皆socket ...

  2. ATMEGA的SPI总线 - 第2部分

    参考: 1.https://www.yiboard.com/thread-783-1-1.html 2.https://mansfield-devine.com/speculatrix/2018/01 ...

  3. 达梦数据库_DM8配置MPP主备

    为了提高MPP系统可靠性,克服由于单节点故障导致整个系统不能继续正常工作,DM 在普通的MPP系统基础上,引入主备守护机制,将MPP节点作为主库节点,增加备库作为备份节点,必要时可切换为主库代替故障节 ...

  4. ubuntu 19.10 中防火墙iptables配置

    $sudo which iptables   /usr/sbin/iptables说明有安装 如果没有安装,那么使用sudo apt-get install iptables 安装. 刚装机,是这个样 ...

  5. Linux系统常用API总结

    1.错误处理 - fprintf() - perror() 2.通用I/O模型 - fd = open(pathname, flags, mode) - numread = read(fd, buff ...

  6. day11 Pyhton学习

    一.昨日内容回顾 函数的进阶 动态传参 *args : 位置参数的动态传参 **kwargs: 关键字参数的动态传参 形参:聚合 实参:打散 顺序:位置参数>*args >默认值 > ...

  7. day18 Pyhton学习 匿名函数

    匿名函数 别称: lambda表达式 函数,没有名字 def wahaha(n):#wahaha return n**2 print(wahaha.__name__) qqxing = lambda ...

  8. 网络编程—【自己动手】用C语言写一个基于服务器和客户端(TCP)!

    如果想要自己写一个服务器和客户端,我们需要掌握一定的网络编程技术,个人认为,网络编程中最关键的就是这个东西--socket(套接字). socket(套接字):简单来讲,socket就是用于描述IP地 ...

  9. 【转载】动态规划—各种 DP 优化

    原博客地址 关于氵博客:其实主要是防止我找不到这篇文了

  10. Golang 随机生成中国人姓名

    package main import ( "fmt" "math/rand" "time" ) var lastName = []stri ...