jvm的解释器和编译器是如何进行协作执行代码的

☕【Java原理探索】彻底你明白什么是JIT编译器(Just In Time编译器) 前提概要 我们都知道开发语言整体分为两类,一类是编译型语言,一类是解释型语言。那么你知道二者有何区别吗?编译器和解释器又有什么区别? 这是为了兼顾启动效率和运行效率两个方面。Java程序最初是通过解释器进行解释运行的,当虚拟机返现某个方法或代码块的运行特别频繁时,就会把这段代码标记为热点代码,为了提供热点代码的运行效率,在运行时,虚拟机就会把这些代码编译成与本地平台相关的机器码。并进行各种层次的优化。 编译器和解释器 Java编译器(javac)的作用是将java源程序编译成中间代码字节码文. 阅读详情

转发:https://www.jianshu.com/p/96d65e8f4cbf

概述

       做为Java开发人员,我们编写的代码是以“.java”为文件后缀的,也就是常说的源码。源码在经过javac命令编译之后,就会生成一个对应“.class”文件,这个就是字节码文件。它为Java的一次编译,到处运行提供了基础。通过JVM的映射,同一份字节码文件,可以在不同的系统上运行,这里就得益于JVM的内部处理了,即:通过JVM屏蔽了底层硬件的差异。但实际上字节码文件还不能算编译完成,它是一个“半成品”,通过JVM内部的处理,才能够转换成处理器能够识别的指令代码。

 

 

       一般地将Java代码的编译分为两个阶段:前端编译和后端编译。前面说的class字节码文件就是前端编译的产物,后端编译最终的结果就是将其转换成计算机能够识别的机器语言。这里引用Hollis大神博客的一张图:

前后端编译过程.png

       这里不去深入探究具体的【词法分析】、【语法分析】、【语义分析】的具体工作原理,只要明白这些步骤是生成字节码文件所必要的校验过程就行。它们实际上就是对源代码进行各种语法层面以及语义层面的校验,以保证最终生成的字节码是标准的、没有语法和语义上的错误。

       通过上图可以看到,前端编译的最终产物是【中间代码】,这个中间代码所指的就是Java的字节码文件。因为代码到了这里还不具有被处理器运行的能力,还需要一层JVM的加工,将其与具体操作系统相关联,生成针对所处系统的机器语言代码,此时机器代码才具有被处理器识别并执行的能力。

解释器(Interpreter)

       解释器顾名思义就是解释代码用的,上面提到了前端编译的最终产物是中间代码,这时的中间代码不具有被处理器识别并执行的能力,解释器的职责就是将此时的字节码逐条解释成处理器能够识别的机器码指令。所以从这里也可以解释,为什么高级语言执行效率会这么慢,主要就是多了这个解释的过程,像Java、Python等执行效率都比较慢。所以通俗讲:解释器在Java中的作用充当了Java程序和计算机之间的“翻译官”角色,将计算机“看”不懂的语言翻译成它能够“看”懂并执行的机器语言。

及时编译器(JIT)

       因为纯粹靠解释器来工作,效率会很慢,JVM引入了及时编译器JIT(Just In Time)的概念,它可以加快Java中部分代码的执行效率。下面简单介绍一下它的工作内容:

 

 

       在我们日常编码中,经常会遇到有些方法执行频率很高,或者有些代码段执行频率很高(例如循环结构)。JVM会随着程序的不断执行,进行深入分析,将程序中那些执行频率比较高的方法或者代码段编译成机器码,然后将这段机器码缓存起来,这段代码也就是所谓的“热点”代码,HotSpot由此而得名。一旦代码被缓存,后续如果继续执行这段代码的时候,直接从缓存中获取这段机器码,就可以跳过前面的编译阶段,执行效率得到极大提高。请看下面这张图,很好地解释了JIT的工作原理:

JIT工作原理.png

       这里可能会有疑问:“既然缓存机器码执行效率那么高,为什么还会有热点代码判断?干脆全部进行缓存不是更好?”这实际上也是一种策略,因为有很多代码(大部分)都是之执行一次,如果这种代码也要进行缓存,完全是在浪费资源。而如果一段代码被多次执行,那么浪费这一次的编译就会换来后续非常客观的效率回报。

       这里还有一个概念--栈上替换(OSR) :在有的时候,可能某段循环执行的代码还在不停的循环中,如果在某次循环之后,计数器达到了某一阈值,这时JVM已经认定这段代码是热点代码,此时编译器会将这段代码编译成机器语言并缓存后,但是这段循环仍在执行,JVM就会把执行代码替换掉,那么等循环到下一次时,就会直接执行缓存的编译代码,而不需要必须等到循环结束才进行替换,这个就是所谓的栈上替换。

热点检测

想要进入JIT,就必须要通过热点代码的筛选,目前JVM的热点探测(Hot Spot Detection)主要有两种方式:

  • 基于采样的热点探测(Sample Based Hot Spot Detection):周期性地检测各个线程的栈顶,如果发现某个方法经常出现在栈顶,换句话说就是某个方法频繁被调用,导致频繁入栈和出栈,那么就可以认为这个方法是热点代码。它的缺点是无法精确确认一个方法的热度,容易受线程阻塞或别的原因干扰探测的准确性。

  • 基于计数器的热点探测(Counter Based Hot Spot Detection):这种探测方式会为每个方法,甚至是代码段添加两个计数器,用于统计执行的次数,它们一旦超过某种阈值,就判定为这段代码为热点代码。HotSpot虚拟机中采用的就是这种热点探测方法。这两个计数器分别是:方法计数器(用于统计方法调用次数)和回边计数器(统计for或者while的运行次数的计数器 )。

JIT运行模式

       JIT的运行模式有两种:client模式和server模式。这两种模式采用的编译器是不一样的,client模式采用的是代号为C1的轻量级编译器,特点是启动快,但是编译不够彻底;而server模式采用的是代号为C2的编译器,特点是启动比较慢,但是编译比较彻底,所以一旦服务起来后,性能更高。可以通过java -version命令查看当前系统中安装的jvm使用的是那种模式:

JavaVersion命令截图.png

       可以看到,我这里使用的是server模式。但是也可以看到后面有个【mixed mode】字样,这表示编译器和解释器采用的是混合模式,即:这两者会同时工作,根据具体的情况,采用不同的运行策略。

       另外,在jdk6u25之后,引入了分层编译的概念,它实际上就是一种渐进的编译策略,在系统运行初期,执行频率较高的代码采用C1编译器编译 ,随着时间的推移,执行频率较高的代码会再次被G2编译器编译,以达到最高的性能。分层编译实际上可以分为五层:

  • 第0层(解释层)启动:这一层主要是提供了一些比较关键性方法的性能,快速进入C1层。

  • 第1层(C1编译器):通过上一层提供的一些关键方法的性能信息来优化这些代码。本层不包含性能优化的信息。

  • 第2层:这一层仍然是基于C1编译器优化的结果来处理的,此时会有少数方法通过C1编译器的编译,在本层会为这些少数方法的调用次数和循环分支执行情况,收集它们的性能分析信息。

  • 第3层:这一层会得到C1编译器编译的所有方法以及对所有的性能优化信息

  • 第4层:这一层只对C2编译器有效。

优化

优化代码缓存

       提到优化,首先就不得不说缓存空间的大小,由于在运行期间,随着热点代码的不断缓存,可能会出现缓存空间不足的情况,此时一旦缓存空间被填满,后续的热点代码就无法进入,那么程序的性能必然会因此而下降,所以设置缓存空间的大小是很有必要的,目的是要最大程度保证热点代码都能被编译。并且编译器的选择不同,它的代码缓存大小也是不一样的,在OpenJDK中,如果是分层编译的话,代码缓存默认大小是240M,如果是不分层编译,缓存大小默认只有48M,这里可以使用 –XX:ReservedCodeCacheSize选项来增加缓存区的大小。另外还有一个:-XX:InitialCodeCacheSize 选项,它用来指定代码缓存空间的初始大小。

       代码缓存空间大小并不是可以无限增大的,假如JVM是32位,那么运行程序的大小就不能超过4GB,缓存内存也是包含在这个4GB空间内的,在具体应用场景中需要结合实际情况来选择最优的缓存空间大小。

优化编译阈值

       前面说过,对于热点代码的识别,主要就是通过方法的进入次数以及代码块的循环执行次数来确定,那么具体这个次数达到多少才能被认为是热点代码?这个值就是编译阈值。标准编译是被-XX:CompileThreshold 这个选项的值所触发的。client模式下它的默认值是1500,server模式下,默认值是10000,如果改变这里的阈值,会使得编译器在相对正常的情况下提前(或推迟)编译代码。改变阈值是比较流行的做法。

其他优化策略

       其他的方式基本都不是直接作用于编译器的设置上,而是一些分析手段,通过具体的内存情况分析,找出问题出现的原因,并且以此找到合理的解决方案。

  • 可以使用-XX:+PrintCompilation,它的默认值是false,添加该选项运行程序,可以打印出编译日志。

  • 也可以使用jstat命令查看一些可见性信息,如果程序启动时没有添加PrintCompilation选项,可以考虑使用此方法:

jstat命令使用.PNG

       当然还有一些其他的概念:内联、向量化、范围检查消除、循环展开等等,这些概念在还有待研究,这里就不做深入解释了。



作者:still_loving
链接:https://www.jianshu.com/p/96d65e8f4cbf
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

JVM 解释器和即时编译器有什么区别? JVM 解释器和即时编译器 (JIT) 是 Java 虚拟机 (JVM) 中执行 Java 字节码的两种核心机制,它们在执行方式、性能特点和应用场景上存在显著差异。例如,在性能调优时,可以关注 JIT 编译器的优化效果,分析热点代码,并采取相应的措施来提升性能。HotSpot VM (最常用的 JVM 实现) 默认采用。 阅读详情

相关推荐

【JVM源码解析】模板解释器解释执行Java字节码指令(下)

本文由HeapDump性能社区首席讲师鸠摩(马智)授权整理发布 第22篇-虚拟机字节码之运算指令 虚拟机规范中与运算相关的字节码指令如下表所示。 0x60 iadd 将栈顶两int型数值相加并将结果压入栈顶 0x61 ladd 将栈顶两long型数值相加并将结果压入栈顶 0x62 fadd 将栈顶两float型数值相加并将结果压入栈顶 0x63 dadd 将栈顶两double型数值相加并将结果压入栈顶 0x64 isub 将栈顶两int型数值相减并将结果压入栈顶 .

HeapDump性能社区的博客 1485

JVM--12---执行引擎----解释器、JIT 编译器

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录执行引擎 执行引擎

时光里的博客 873

Java 答疑:编译器和解释器有何区别?Java 语言属于编译型编程语言还是解释型编程语言?_java解释器和编译器的区别

我们都知道开发语言整体分为两类,一类是编译型编程语言,一类是解释型编程语言。那么你知道二者有何区别吗?编译器和解释器又各自有何区分?Java 语言属于编译型编程语言还是解释型编程语言呢?编译器是将源代码编译(翻译)成低级语言的程序。编译器把源程序的每一条语句都编译成机器语言,并保存为二进制文件,运行时计算机可以直接通过运行语言来运行此程序,速度会很快。英文译文解释器是直接执行用编程语言编写的指令的程序。只有在执行程序时,才一条一条的解释成机器语言给计算机来执行,所以运行速度不如编译后的程序运行的快。

2401_87022483的博客 1345

JVM 解释器

一点睛 JVM 设计者们的初衷仅仅只是单纯地为了满足 Java 程序实现跨平台特性,因此避免采用静态编译的方式直接生成本地机器指令,从而产生了实现解释器在运行时采用逐行解释字节码执行程序的想法。 为什么 Java 源文件不直接翻译成 JVM ,而是翻译成字节码文件?可能是因为直接翻译的代码工作量比较大。 解释器真正意义上所承担的角色就是一个运行时的“翻译者”,将字节码文件中的内容“翻译”为对应平台的本地机器指令执行。 当一条字节码指令被解释执行完成后,接着再根据 PC 寄存器中记录的下一条需要.

实践求真知 1100

CMU动作捕捉数据集实战:从AMC文件到Python可视化的完整流程

本文提供了CMU动作捕捉数据集的完整实战指南,详细解析了AMC文件格式,并对比了MATLAB转换、Python原生解析及转换为BVH格式三种数据解析策略。重点介绍了如何构建Python数据处理与可视化管道,包括将数据转换为Pandas DataFrame、绘制时间序列与相关性热力图,以及实现3D骨架动画,帮助开发者高效利用这一经典动作捕获数据集进行运动分析与模型训练。

android的专栏 716

【CubeMX】STM32G474 HRTIM 死区时间与互补PWM实战解析

本文深入解析STM32G474的HRTIM高分辨率定时器在互补PWM生成与死区时间配置中的应用。通过CubeMX工具详细演示时钟配置、单路PWM基础、互补输出与死区时间设置,并结合逆变器等电力电子实战案例,帮助开发者避免直通风险,优化系统性能。

efc12345678的博客 746

JVM的执行引擎

执行引擎、包括解释器和JIT编译器的介绍

scj1022的博客 2114

《uni-app 长列表优化:虚拟列表(vue-virtual-scroller)解决 1000+ 数据渲染卡顿》(附虚拟列表封装与多端适配)

本文详细介绍了虚拟列表技术在前端长列表渲染中的优化方案。针对传统v-for渲染导致的性能问题(内存占用高、渲染阻塞、滚动卡顿),提出基于vue-virtual-scroller的虚拟列表解决方案,通过可视区域渲染和DOM复用实现性能突破。文章包含核心原理、组件封装、多端适配及性能对比,并给出常见问题的解决方法。实践表明,该方案可将1000条数据的首次渲染时间从3800ms降至420ms,滚动FPS提升至55帧,显著改善用户体验。

qq_59041750的博客 2107

JVM之执行引擎

文章目录执行引擎概述Java代码编译和执行过程什么是解释器( Interpreter),什么是JIT编译器?为什么说Java是半编译半解释型语言?机器码、指令、汇编语言机器码指令指令集汇编语言高级语言字节码C、C++源程序执行过程解释器JIT编译器HotSpot VM 为何解释器与JIT编译器共存热点代码及探测方式方法调用计数器热度衰减回边计数器HotSpot VM 可以设置程序执行方式HotSpot VM 中的JIT分类C1和C2编译器不同的优化策略 执行引擎概述 执行引擎是Java虚拟机的核心组成部

学海无涯乐作舟 908

ESP-IDF的安装及其在VScode中编译环境的搭建

从安装目录的\Espressif\frameworks\esp-idf-v5.3.2\examples路径中拷贝一个工程到项目中,比如拷贝\get-started下的hello_world文件夹。安装时可能会遇到如下问题,提示:"e:\ssc\software\ESP-IDF\v5.3.2\Espressif\tools\idf-python\3.11.2\python.exe -m pip" is not valid. (ERROR_INVALID_PIP)接着等待安装完成即可,其他步骤同方式1。

Freddy_Ssc的博客 4365

【STM32 CubeMX】I2C中断方式与DMA方式

在STM32 CubeMX环境中,I2C(Inter-Integrated Circuit)通信协议的实现可以采用中断方式或DMA(Direct Memory Access)方式。中断方式通过触发中断来处理数据传输,而DMA方式则利用直接内存访问技术来实现数据传输,减轻了CPU的负担。在选择I2C通信方式时,开发者需要根据具体的应用需求和性能要求来选择合适的方式。STM32 CubeMX提供了图形化配置工具,使得配置I2C通信方式变得更加便捷。

m0_62599305的博客 7744

一文让你“一夜封神“深入理解JVM一一简介和体系结构

➢通过计数器找到最具编译价值代码,触发即时编译或栈上替换➢通过编译器与解释疑协同工作,在最优化的程序响应时间与最佳执行性能中取得平衡虚拟机和Java虚拟机区别虚拟机===就是一台虚拟的计算机。它是一款软件,用来执行一系列虚拟计算机指令。虚拟机可以分为系统虚拟机和程序虚拟机。大名鼎鼎的Visual Box,Mware就属于系统虚拟机,它们完全是对物理计算机的仿真,提供了一个可运行完整操作系统的软件平台。

2401_84408814的博客 670

【教程4>第4章>第22节】FFT频偏估计方法,导频+cordic频偏估计方法,costas环的性能对比

频偏范围适应性:Costas 环频偏锁定和基于 PN 导频和 CORDIC 算法的频偏估计都可以通过调整参数来适应一定范围的频偏,但 Costas 环的频率捕获范围相对较窄,而基于 PN 导频和 CORDIC 算法的频偏估计,基于 FFT 变换频偏估计对频偏范围较大。在高信噪比条件下,三种方法都可以获得较高的估计精度,但在低信噪比环境中,基于 PN 导频和 CORDIC 算法的频偏估计,基于 FFT 变换频偏估计这两个开环方案相对更具优势,而Costas 环频偏锁定的精度可能会受到较大影响.

FPGA/MATLAB学习教程/源码/项目合作开发 609

【jvm系列-07】深入理解执行引擎,解释器、JIT即时编译器

深入理解jvm中执行引擎的工作原理

zhenghuishengq的博客 9765

ParaView: 从 2 或 3 个标量创建向量

ParaView: 从 2 或 3 个标量创建向量

希望我的博客,能帮上你解决学习中工作中所遇到的问题 585

深信服全产品线新版图标库 Visio版+PPT版【2023年最新整理】

深信服全产品线新版图标库Visio版(含网络位置符号以及其他网络设备和外设图标)有朋友想要我整理一下深信服的相关图标,那么今天,瑞哥给老铁们整理了。运维漫谈是瑞哥针对运维领域的一个公众号,欢迎大家的关注哦!篇幅原因,就只展示那么多,有需要的朋友自行下载。SANGFOR 各产品图标-Visio版。你好,这里是网络技术联盟站。SANGFOR全产品线图标。深信服设备前置面板-AC。

网络技术联盟站 3694

JVM执行引擎——解释器和即时编译器

什么是JVM执行引擎? 执行引擎是Java虚拟机四大组成部分中另一个核心组成(另外三个分别是类加载器子系统、运行时数据区、垃圾回收器),Java虚拟机的执行引擎主要是用来执行Java字节码。JVM的执行引擎执行字节码通过两种解释器执行的:字节码解释器与模板解释器,运行过程中,可能会触发即时编译(JIT),涉及到几种即时编译器,下面分别进行介绍。 字节码解释器 字节码解释器是解释执行的,所谓解释执行,就是将Java字节码转成C++代码,再将C++代码编译成本地代码(硬编码),之所以会转成C++代码.

jb84006的博客 2818

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

JVM解释器和编译器

许多人认为Java是一门解释执行的语言,由虚拟机解释执行class文件字节码。事实是Java是一门解释执行和编译执行并存的语言。JVM解释器让Java程序快速启动,编译器让Java程序高效运行,这是Java长久生存的一大重要原因。 解释器与编译器的关系 在一个Java程序执行时,首先通过javac把java文件编译为虚拟机可以识别的class文件。然后由JVM解释器解释class文件...

yan245294305的博客 2757

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

JVM的解释器和即时编译器JIT

参考网址 https://www.cnblogs.com/linghu-java/p/8589843.html. 1 什么是Java编译器   Java编译器:将Java源文件(.java文件)编译成字节码文件(.class文件,是特殊的二进制文件,二进制字节码文件),这种字节码就是JVM的“机器语言”。javac.exe可以简单看成是Java编译器。 2 JVM内的解释器和即时编译器器   什么是机器码?   机器码就是用二进制代码表示的计算机能直接识别和执行的一种机器指令的集合。   而解释器和即时编.

qq_39164234的博客 2776

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

jvm执行引擎全解,java解释器即时编译器,全都讲明白

目录 一、开局一张图 二、执行引擎概述 三、执行引擎工作过程 java代码编译和执行的过程 问题:什么是解释器(Interpreter),什么是JIT编译器? 问题:为什么说java是半编译半解释型语言? 四、机器码、指令、汇编语言等概念 机器码 指令 指令集 汇编语言 高级语言 字节码 C、C++源程序执行过程: 图示,各种语言都可以运行在java虚拟机,只要能编译出字节码文件: 图示,java代码处理过程: 图示,高级语言执行过程: 五、解释器 解释器工作机制(或工

秃了也弱了 2502

JVM 执行引擎部分 (编译器、解释器)

介绍了JVM执行引擎中解释器与编译器的区别和Java源程序的执行流程,并且介绍了JVM即时编译器的几种优化手段。

TheAnnoyingDog的博客 1248

JVM解释器与JIT编译器如何并存?

由于Java虚拟机规范并没有具体的约束规则去限制即使编译器应该如何实现,所以这部分功能完全是与虚拟机具体实现相关的内容,如无特殊说明,我们提到的编译器、即时编译器都是指Hotspot虚拟机内的即时编译器,虚拟机也是特指HotSpot虚拟机。解释器真正意义上所承担的角色就是一个运行时“翻译者”,将字节码文件中的内容“翻译”为对应平台的本地机器指令执行,当一条字节码指令被解释执行完成后,接着再根据PC寄存器中记录的下一条需要被执行的字节码指令执行解释操作。只有对频繁执行的代码,JIT编译才能保证有正面的收益。

十一月廿七风雨大作 8802

java基础一JVM之JRE、JDK、解释器、编译器详解

java基础——JVM之JRE、JDK、解释器、编译器详解

江哈哈的博客 2566

【个人学习】JVM(9): 执行引擎、解释器、JIT编译器、其他编译器

解释器:当Java虚拟机启动时会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容“翻译”为对应平台的本地机器指令执行。JIT(Just In Time Compiler)编译器:就是虚拟机将源代码一次性直接编译成和本地机器平台相关的机器语言,但并不是马上执行。为什么Java是半编译半解释型语言?JDK1.0时代,将Java语言定位为“解释执行”还是比较准确的。再后来,Java也发展出可以直接生成本地代码的编译器。

dopapapa的博客 1230

JVM执行引擎篇(解释器与编译器)

解释器与编译器1.编译和执行的过程2.编译器和解释器3.解释器详解4.编译器详解5.执行方式设置 1.编译和执行的过程 大部分的程序源代码转换成物理机的目标代码或虚拟机能执行的指令集之前,都需要经历如下步骤 代码编译由Java源码编译器javac完成 代码执行由Java虚拟机执行引擎完成 2.编译器和解释器 解释器 当Java虚拟机启动时会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容“翻译”为对应平台的本地机器指令执行 编译器 就是虚拟机将源代码直接

ProChick's Blog 1340
上一篇: Java之深入JVM - 字节码执行引擎(转)
下一篇: Java中几种常量池的区分
蓝猫_虹
博客等级 码龄12年 49粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值