浅析 JIT 即时编译技术
即时编译回顾
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 即时编译技术的更多相关文章
- java 笔记(1)-—— JVM基础,内存数据,内存释放,垃圾回收,即时编译技术JIT,高精度类型
1.java中5个存放数据的地方: (1).寄存器(Registers):位于CPU内部,是速度最快的存储区,但是数量和容量有限.在java中不能直接操作寄存器. (2).栈(Stack):栈位于通用 ...
- JIT——即时编译的原理
介绍 java 作为静态语言十分特殊,他需要编译,但并不是在执行之前就编译为本地机器码. 所以,在谈到 java的编译机制的时候,其实应该按时期,分为两个部分.一个是 javac指令 将java源码 ...
- 为什么 JVM 不用 JIT 全程编译?
考虑到跨平台,所以无法使用AOT: 考虑到执行效率,所以无法全部使用JIT: 编译技术大约分为两种,一种AOT,只线下(offline)就将源代码编译成目标机器码,这是普遍用在系统程序语言中:另一种是 ...
- JIT(动态编译)和AOT(静态编译)编译技术比较
Java 应用程序的性能经常成为开发社区中的讨论热点.因为该语言的设计初衷是使用解释的方式支持应用程序的可移植性目标,早期 Java 运行时所提供的性能级别远低于 C 和 C++ 之类的编译语言.尽管 ...
- 即时编译(JIT)
即时编译(JIT : just-in-time compilation): 指计算机领域里,即时编译也被成为动态翻译,是一种通过在运行时将字节码翻译为机器码,从而改善字节码编译语言性能的技术 即时编译 ...
- JVM即时编译(JIT)
Java解释执行过程: 代码装入-代码校验-代码执行 Java字节码的执行方式分为两种:即使编译方式和解释执行方式.即时编译是值解释器先将字节码编译成机器码,然后执行该机器码.解释执行的方式是指解释器 ...
- Java 面试-即时编译( JIT )
当我们在写代码时,一个方法内部的行数自然是越少越好,这样逻辑清晰.方便阅读,其实好处远不止如此,通过即时编译,甚至可以提高执行时的性能,今天就让我们好好来了解一下其中的原理. 简介 当 JVM 的初始 ...
- 转:什么是即时编译(JIT)!?OpenJDK HotSpot VM剖析
重点 应用程序可以选择一个适当的即时编译器来进行接近机器级的性能优化. 分层编译由五层编译构成. 分层编译提供了极好的启动性能,并指导编译的下一层编译器提供高性能优化. 提供即时编译相关诊断信息的JV ...
- JIT(Just in time,即时编译,边运行边编译)、AOT(Ahead Of Time,运行前编译),是两种程序的编译方式
JIT(Just in time,即时编译,边运行边编译).AOT(Ahead Of Time,运行前编译),是两种程序的编译方式
随机推荐
- 在Linux系统下搭建和配置一个minio文件服务器(二)
上一篇主要讲述了在linux系统中搭建一个minio文件服务器,那么这一篇则用来整合java代码中使用,我之前自己已经搭建好了一个springboot项目,那么这一篇将详细讲述如何把minio整合进s ...
- Java 实现常见内排序
一.内排序 1.排序基本概念 (1)什么是排序? 排序指将一个数据元素集合或者序列 按照某种规则 重新排列成一个 有序的集合或者序列.分为内排序.外排序.排序算法的好坏直接影响程序的执行速度以及存储空 ...
- django 的初始项目结构
2.创建Django项目 root@dev:shiyanlou_project# workon syl (syl) root@dev:shiyanlou_project# cd /aaa/shiy ...
- React学习小记--setState的同步与异步
react中,state不能直接修改,而是需要使用setState()来对state进行修改,那什么时候是同步而什么时候是异步呢? 基础代码: setCounter = (v) => { thi ...
- Book of Shaders 00 - 使用 VS Code 编写 GLSL
0x00 写在前面 最近在学习由 Patricio 编写的 The Book of Shaders,这是一本关于 Fragment Shaders(片段着色器)的入门指南.为了在一个相对熟悉的平台运行 ...
- 02 ArcPython的使用大纲
一.什么情况下使用ArcPython? 1.现有工具实现不了,可以用python 2.流程化需要时,可以使用python 3.没有AE等二次开发环境 4.其他特殊场景 二.ArcPython在ArcG ...
- shell-的特殊变量-进程状态变量$$ $! $? $_详解
一:shell的特殊变量-进程状态变量详解 1. 进程状态变量 $$ 获取当前shell的进程号(pid) $! 执行上一个指令的pid,上一个后台运行进程的进程号 $? 获取执行上一个指令的返回值 ...
- 利用HDFS实现ElasticSearch7.2容灾方案
利用HDFS实现ElasticSearch7.2容灾方案 目录 利用HDFS实现ElasticSearch7.2容灾方案 前言 快照版本兼容 备份集群 HDFS文件系统 软件下载 JDK环境 配置系统 ...
- MeteoInfoLab脚本示例:Hamawari-8 netCDF data
示例数据:ftp://ftp.bom.gov.au/anon/sample/catalogue/Satellite/IDE00220.201507140300.nc 该数据的分辨率很高(22000*2 ...
- shell携带附件,Linux下的自解压文件诞生了
初衷 windows下有自解压文件,直接双击就能释放文件,并且还能执行释放文件前后要执行的脚本.Linux下我也想要这样的功能,因为我希望直接拷贝一个shell脚本给别人,别人直接运行就能用,而不是一 ...