JVM执行引擎

news2024/11/24 20:11:52

文章目录

  • 学习资料
  • 执行引擎
    • 概述
    • 工作过程
    • Java代码编译和执行的过程
      • 什么是解释器(Interpreter),什么是JIT编译器?
      • 为什么说Java是半编译半解释型语言?
    • 机器码、指令、汇编语言、高级语言
      • 机器码
      • 指令
        • 指令集
      • 汇编语言
      • 高级语言
    • 字节码、解释器
      • 字节码
      • 解释器
    • 解释器与JIT编译器
      • Java代码的执行分类
      • HotSpot JVM的执行方式
      • JIT编译器
        • 概念解释
        • 热点代码及探测方式
        • 方法调用计数器
          • 热度衰减
        • 回边计数器
        • HotSpot VM可以设置程序执行方式
        • HotSpot VM中JIT分类
          • C1和C2编译器不同的优化策略
          • 分层编译(Tiered Compilation)策略
  • 总结


学习资料

【尚硅谷宋红康JVM全套教程(详解java虚拟机)】
【阿里巴巴Java开发手册】https://www.w3cschool.cn/alibaba_java
JDK 8 JVM官方手册

执行引擎

概述

在这里插入图片描述

执行引擎是Java虚拟机核心的组成部分之一。

“虚拟机”是一个相对于“物理机”的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和 操作系统层面上的,而虚拟机的执行引擎则是由软件自行实现的,因此可以不受物理条件制约地制定指令集与执行引擎的结构体系,能够执行那些不被硬件直接支持的指令集格式

JVM的主要任务是负责装载字节码到其内部,但字节码并不能够直接运行在操作系统之上,因为字节码指令并非等价于本地机器指令,它内部包含的仅仅只是一些能够被JVM所识别的字节码指令、符号表、以及其他辅助信息。

那么,如果想要让一个Java程序运行起来,执行引擎(Execution Engine)的任务就是将字节码指令解释/编译为对应平台上的本地机器指令才可以。简单来说,JVM中的执行引擎充当了将高级语言翻译为机器语言的译者。

工作过程

在这里插入图片描述

从外观来看,所有Java虚拟机的执行引擎输入、输出都是一致的:输入的是字节码二进制流,处理过程是字节码解析执行的等效过程,输出的是执行结果。

Java代码编译和执行的过程

在这里插入图片描述
在这里插入图片描述

什么是解释器(Interpreter),什么是JIT编译器?

解释器:当Java虚拟机启动时会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容“翻译”为对应平台的本地机器指令执行。

JIT(Just In Time Compiler)编译器:就是虚拟机将源代码直接编译和本地机器平台相关的机器语言。

为什么说Java是半编译半解释型语言?

JDK1.0时代,将Java语言定位为“解释执行”还是比较准确的。再后来,Java也发展出可以直接生成本地代码的编译器。

现在JVM执行Java代码的时候,通常都会将解释执行与编译执行二者结合起来进行。

机器码、指令、汇编语言、高级语言

机器码

各种用二进制编码方式表示的指令,叫做机器指令码。开始,人们就用它采编写程序,这就是机器语言。

机器语言虽然能够被计算机理解和接受,但和人们的语言差别太大,不易被人们理解和记忆,并且用它编程容易出差错。

用它编写的程序一经输入计算机,CPU直接读取运行,因此和其他语言编的程序相比,执行速度最快。

机器指令与CPU紧密相关,所以不同种类的CPU所对应的机器指令也就不同。

指令

由于机器码是有0和1组成的二进制序列,可读性实在太差,于是人们发明了指令。

指令就是把机器码中特定的0和1序列,简化成对应的指令(一般为英文简写,如mov,inc等),可读性稍好。

由于不同的硬件平台,执行同一个操作,对应的机器码可能不同,所以不同的硬件平台的同一指令(比如mov),对应的机器码也可能不同。

指令集

不同的硬件平台,各自支持的指令,是有差别的。因此每个平台所支持的指令,称之为对应平台的指令集。

如常见的:
x86指令集,对应的是x86架构的平台
ARM指令集,对应的是ARM架构的平台

汇编语言

由于指令的可读性还是太差,于是人们又发明了汇编语言。

在汇编语言中,用助记符(Mnemonics)代替机器指令的操作码,用地址符号(Symbol)或标号(Label)代替指令或操作数的地址

在不同的硬件平台,汇编语言对应着不同的机器语言指令集,通过汇编语言过程转换成机器指令。
由于计算机只认识指令码,所以用汇编语言编写的程序还必须翻译成机器指令码,计算机才能识别和执行。

高级语言

为了使计算机用户编程序更容易些,后来就出现了各种高级计算机语言。高级语言比机器语言、汇编语言更接近人的语言

当计算机执行高级语言编写的程序时,仍然需要把程序解释和编译成机器的指令码。完成这个过程的程序就叫做解释程序或编译程序。

在这里插入图片描述

字节码、解释器

字节码

在这里插入图片描述

解释器

在这里插入图片描述

解释器真正意义上所承担的角色就是一个运行时“翻译者”,将字节码文件中的内容“翻译”为对应平台的本地机器指令执行。

当一条字节码指令被解释执行完成后,接着再根据PC寄存器中记录的下一条需要被执行的字节码指令执行解释操作。

在Java的发展历史里,一共有两套解释执行器,即古老的字节码解释器、现在普遍使用的模板解释器。

字节码解释器在执行时通过纯软件代码模拟字节码的执行,效率非常低下。

而模板解释器将每一条字节码和一个模板函数相关联,模板函数中直接产生这条字节码执行时的机器码,从而很大程度上提高了解释器的性能。
在HotSpot VM中,解释器主要由Interprenter模块和Code模块构成。
Interpreter模块:实现了解释器的核心功能。
Code模块:用于管理HotSpot VM在运行时生成的本地机器指令。

由于解释器在设计和实现上非常简单,因此除了Java语言之外,还有许多高级语言同样也是基于解释器执行的,比如Python、Perl、Ruby等。但是在今天,基于解释器执行已经沦落为低效的代名词,并且时常被一些C/C++程序员所调侃。

为了解决这个问题,JVM平台支持一种叫做即时编译的技术。及时编译的目的是避免函数被解释执行,而是将整个函数体编译称为机器码,每个函数执行时,只执行编译后的机器码即可,这种方式可以使执行效率大幅度提升。

不过无论如何,基于解释器的执行模式仍然为中间语言的发展做出了不可磨灭的贡献。

解释器与JIT编译器

Java代码的执行分类

第一种是将源代码编译成字节码文件,然后在运行时通过解释器将字节码文件转为机器码执行。

第二种是编译执行(直接编译成机器码)。现代虚拟机为了提高执行效率,会使用即时编译技术(JIT,Just In Time)将方法编译成机器码后再执行。

HotSpot VM是目前市面上高性能虚拟机的代表作之一。它采用解释器与即时编译器并存的架构。在Java虚拟机运行时,解释器和即时编译器能够相互协作,各自取长补短,尽力去选择最合适的方式来权衡编译本地代码的时间和直接解释执行代码的时间。

在今天,Java程序的运行性能早已脱胎换骨,已经达到了可以和C/C++程序一较高下的地步。

HotSpot JVM的执行方式

当虚拟机启动的时候,解释器可以首先发挥作用,而不必等待即时编译器全部编译完成再执行,这样可以省去许多不必要的编译时间。并且随着程序运行时间的推移,即时编译器逐渐发挥作用,根据热点探测功能,将有价值的字节码编译为本地机器指令,以换取更高的程序执行效率。

JIT编译器

概念解释

1、Java语言的“编译期”其实是一段“不确定”的操作过程,因为它可能是指一个前端编译器(其实叫“编译器的前端”更准确一些)把.java文件转变成.class文件的过程;

2、也可能是指虚拟机的后端运行期编译器(JIT编译器,Just In Time Compiler)把字节码转变成机器码的过程。

3、还可能是指使用静态提前编译器(AOT编译器,Ahead Of Time Compiler)直接把.java文件编译成本地机器代码的过程。

前端编译器:Sun的Javac、Eclipse JDT中的增量式编译器(ECJ)。
JIT编译器:HotSpot VM的C1、C2编译器。
AOT编译器:GNU Compiler for the Java (GCJ)、Excelsior JET。

热点代码及探测方式

当然是否需要启动JIT编译器将字节码直接编译为对应平台的本地机器指令,则需要根据代码调用执行的频率而定。关于那些需要被编译为本地代码的字节码,也被称之为“热点代码”,JIT编译器在运行时会针对那些频繁被调用的“热点代码”做出深度优化,将其直接编译为对应平台的本地机器指令,以此提升Java程序的执行性能。

一个被多次调用的方法。或者是一个方法体内部循环次数较多的循环体都可以被称之为“热点代码”,因此都可以通过JIT编译器编译为本地机器指令。由于这种编译方式发生在方法的执行过程中,因此也被称之为栈上替换,或简称为OSR(On Stack Replacement)编译。

一个方法究竟要被调用多少次,或者一个循环体究竟需要执行多少次循环才可以达到这个标准?必然需要一个明确的阈值,JIT编译器才会将这些“热点代码”编译为本地机器指令执行。这里主要依靠热点探测功能

目前HotSpot VM所采用的热点探测方式是基于计数器的热点探测。

采用基于计数器的热点探测,HotSpot VM将会为每一个方法都建立2个不同类型的计数器,分别为方法调用计数器(Invocation Counter)和回边计数器(Back Edge Counter)。
1、方法调用计数器用于统计方法的调用次数。
2、回边计数器则用于统计循环体执行的循环次数。

方法调用计数器

这个计数器就用于统计方法被调用的次数,它的默认阈值在Client模式下是1500次,在Server模式下是10000次。超过这个阈值,就会触发JIT编译。

这个阈值可以通过虚拟机参数-XX:CompileThreshold来人为设定。

当一个方法被调用时,会先检查该方法是否存在被JIT编译过的版本,如果存在,则优先使用编译后的本地代码来执行。如果不存在已被编译过的版本,则将此方法的调用计数器值加1,然后判断方法调用计数器与回边计数器值之和是否超过方法调用计数器的阈值。如果已超过阈值,那么将会向即时编译器提交一个该方法的代码编译请求。

在这里插入图片描述

热度衰减

如果不做任何设置,方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,即一段时间之内方法调用的次数。当超过一定的时间限度,如果方法的调用次数仍然不足以让它提交给即时编译器编译,那这个方法的调用计数器就会被减少一半,这个过程称为方法调用计数器热度的衰减(Counter Decay),而这段时间就称为此方法统计的半衰周期(Counter Half Life Time)

进行热度衰减的动作是在虚拟机进行垃圾收集时顺便进行的,可以使用虚拟机参数-XX:-UseCounterDecay来关闭热度衰减,让方法计数器统计方法调用的绝对次数,这样,只要系统运行时间足够长,绝大部分方法都会被编译成本地代码。

另外,可以使用-XX:CounterHalfLifeTime参数设置半衰周期的时间,单位是秒。

回边计数器

它的作用是统计一个方法中循环体代码执行的次数,在字节码中遇到控制流向后跳转的指令称为“回边(Back Edge)”。显然,建立回边计数器统计的目的就是为了触发OSR编译。
在这里插入图片描述

HotSpot VM可以设置程序执行方式

缺省情况下HotSpot VM是采用解释器与即时编译器并存的架构,当然开发人员可以根据具体的应用场景,通过命令显示地为Java虚拟机指定在运行时到底是完全采用解释器执行,还是完全采用即时编译器执行。如下所示:

默认混合模式
在这里插入图片描述

-Xint:完全采用解释器模式执行程序。CMD框中命令:java -Xint -version
在这里插入图片描述

-Xcomp:完全采用即时编译器模式执行程序。如果即时编译出现问题,解释器会介入执行。CMD框中命令:java -Xcomp -version
在这里插入图片描述

-Xmixed:采用解释器+即时编译器的混合模式共同执行程序。CMD框中命令:java -Xmixed -version
在这里插入图片描述

HotSpot VM中JIT分类

在HotSpot VM中内嵌有两个JIT编译器,分别为Client Compiler和Server Compiler,但大多数情况下我们简称C1编译器和C2编译器。开发人员可以通过如下命令显式指定Java虚拟机在运行时到底使用哪一种即时编译器,如下所示:

-client:指定Java虚拟机运行在Client模式下,并使用C1编译器;
C1编译器对字节码进行简单和可靠的优化,耗时短。已达到更快的编译速度。

-server:指定Java虚拟机运行在Server模式下,并使用C2编译器。
C2进行耗时较长的优化,以及激进优化。但优化的代码执行效率更高。

C1和C2编译器不同的优化策略

在不同的编译器上有不同的优化策略,C1编译器上主要有方法内联,去虚拟化、冗余消除。
方法内联:将引用的函数代码编译到引用点处,这样可以减少栈帧的生成,减少参数传递以及跳转过程。
去虚拟化:对唯一的实现类进行内联。
冗余消除:在运行期间把一些不会执行的代码折叠掉。

C2优化主要是在全局层面,逃逸分析是优化的基础,基于逃逸分析在C2上有如下几种优化:
标量替换:用标量值代替聚合对象的属性值。
栈上分配:对于未逃逸的对象分配对象在栈而不是在堆。
同步消除:清除同步操作,通常指synchronized。

分层编译(Tiered Compilation)策略

程序解释执行(不开启性能监控)可以触发C1编译,将字节码编译成机器码,可以进行简单优化,也可以加上性能监控,C2编译会根据性能监控信息进行激进优化。

不过在Java7版本之后,一旦开发人员在程序中显式指定命令“-server”时,默认将会开启分层编译策略,由C1编译器和C2编译器相互协作功能来执行编译任务。

总结

一般来讲,JIT编译出来的机器码性能比解释器高。
C2编译器启动时长比C1编译器慢,系统稳定执行以后,C2编译器执行速度远远快于C1编译器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/14104.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UE5实现PS图层样式投影效果

一、PS图层样式投影效果 1、创建材质函数 MF_PS_Style_Shadow 公开到库(可选) 定义 function input。 Shadow代码: /** PS图层样式投影效果param {UVs} texture coordinateparam {TextureObject} texture objectparam {TextureSize} …

十、children的深入用法-React.Children对象上的方法

目标 理解什么是children掌握React.Children对象上的方法 知识点 什么是children上图中我们看到了,我们之前学过的React.createElement方法,现在大家发现jsx的内容,全部都体现在了该方法上;那么React.createElement其实是有三个…

专精特新企业数据集两份数据

专精特新企业数据集 一、三批专精特新上市、非上市公司数据分布 1、时间截止至2021年8月 2、区域范围:上市和非上市公司两大板块,涵盖申万一级行业 3、指标说明: 包含如下内容:专精特新上市公司名单汇总、第一批专精特新上市公…

opencv 入门学习

opencv 演示 输入说明 原图在顶层后然后再去按键,不然会失效(未知原因) 1.roberts 边缘检测 2.sobel算子 3.Canny算子 4.Laplace算子 5.Canny算子,轮廓显示 空格 人脸检测准备一张图片效果 默认显示原图和灰阶图 roberts 边缘…

MySQL版本号6和7去哪了

问题 MySQL版本号6和7去哪了 详细问题 笔者起初误以为MySQL版本号6和7可能由于存在诟病不受欢迎或由于MySQL版本迭代过快导致未能在市场上流行 但是在浏览MySQL官网注意到 MySQL在2017年发布了新的版本8.0,但是在此之前的上一一个版本是5.7,40,那么中间的6和7去哪…

并发编程永远绕不开的难题,跟着大牛带你Java并发编程从入门到精通

我们知道,很多框架或者自研组件的底层,都或多或少涉及到并发编程方面的技术点。 比如:在一些本地缓存组件中,当本地缓存过期后,需要从数据库加载数据,这个阶段中就会涉及到线程并发请求的处理;在…

微信小程序云开发

概念 小程序云开发,让前端程序员拥有后端的能力云函数 (nodejs)云数据库 (mogodb)云存储前端写好云函数 > 上传到云服务器 >实现自定云部署前端去调用云函数>间接通过云函数对数据库的操作前端>全栈 注意…

DSP之寄存器映射和CDM文件

DSP之寄存器映射和CDM文件 RAM:程序运行速度快,关掉电源,程序会丢失。 Flash:程序运行速度慢,关掉电源,程序不会丢失。 所以,程序一般存到Flash中,在运行的时候,由CPU将…

2010-2019年208个地级市城乡收入差距泰尔指数

2010-2019年208个地级市城乡收入差距泰尔指数 1、数据来源:各省的统计NJ以及部分地级市的NJ(主要是地级市的城镇化率) 城镇化率为常驻人口城镇化率而非户籍人口城镇化率。附件中也包含各个地级市的城镇化率,农村人均可支配收入2…

Linux开发工具(1)——yum

文章目录软件包管理器 —— yum安装软件的三个问题Linux开源生态yum查找软件yum下载软件yum删除软件配置yum源Linux下的工具本质也是指令 , 下面我会介绍几个常用的工具 , 分别是yum(相当于是手机上的应用商店 , 可以在里面下载工具 ) vim(多模式编辑器)…

【毕业设计】深度学习行人车辆流量计数系统 - 目标检测 python

文章目录0 前言1. 目标检测概况1.1 什么是目标检测?1.2 发展阶段2. 行人检测2.1 行人检测简介2.2 行人检测技术难点2.3 行人检测实现效果2.4 关键代码-训练过程3 最后0 前言 🔥 Hi,大家好,这里是丹成学长的毕设系列文章&#xff…

机器学习-SVM算法

文章目录支持向量机1. 间隔与支持向量1.1. 点到超平面的距离1.2. 去掉绝对值1.3. 最大间隔2. 对偶问题2.1. 引入拉格朗日乘子2.2. 求偏导2.3. 得到对偶问题2.4. 求解内层函数 minw,bL(w,b,α)min_{w,b} L(w,b,\alpha)minw,b​L(w,b,α)2.5. 求解外层函数 maxαminw,bL(w,b,α)m…

.ko 加载报错 “unknown symbol in module or invalid parameter” 排查解决方法

.ko 加载报错 “unknown symbol in module or invalid parameter” 排查解决方法 问题来源 今天参照Sigmastar的文档,修改config重新编译kernel,打开板上RNDIS虚拟网口。 按照步骤重编后,在demo.sh加入insmod指令,按顺序在启动…

【计算机网络】—网络编程(socket)02

目录 一、网络编程的概念 二、UDP数据报套接字编程 2.1 回显服务器代码 2.2 翻译程序(英译汉) 三、TCP数据报套接字编程 3.1回显服务器 3.2 翻译服务器 一、网络编程的概念 网络编程:指网络上的主机,通过不同的进程&#x…

openlayer+ol-ext 裁剪 天地图 中国或者其他省份 范围进行展示

地图未裁剪或遮盖效果(天地图) 效果1.crop: 1.1裁剪天地图里面效果 参数: inner: true 1.2裁剪天地图外面 参数: inner: false 核心代码: let crop new Crop({feature: feature[0],inner: false,});vecLayer.addF…

【保姆级】新机器部署JDKTomcat

1、登录服务器,如果非root用户则切root用户 sudo su - 2、在/usr/tmp目录上传JDK、Tomcat安装包 3、将安装包移到/usr/lib目录 mv xxx /usr/lib 4、解压 & 重命名 tar -xzvf xxx mv xxx jdk、mv xxx tomcat 5、配置环境变量 vim /etc/profile JAVA_HOME/u…

引用参考文献[1,2]或者[1-3]

目录准备参考视频引用参考文献[1,2]引用参考文献[1-3]准备 word 2021 参考视频 word中同一位置引用多篇参考文献角标设置 引用参考文献[1,2] 把参考文献交叉引用到文章中,如下图所示 选中标签[1][2] ,点击切换域代码: 然后如下图所示 …

递归经典例题 --- 青蛙跳台阶(图文详解)

目录 一、介绍 二、解题思路 介绍动态规划法 三、代码实现 一、介绍 所谓的青蛙跳台阶问题,就是指一只青蛙一次可以跳上1级台阶,也可以跳上2级(最多只能跳2级)。求该青蛙跳上一个n级的台阶总共有多少种跳法。 二、解题思路 首…

Spring核心解析—Resource与ResourceLoader接口

Resource你不得不知的事情前言Resource内容继承结构DOC解释提供的功能重要的内置Resource实现UrlResourceClassPathResourceFileSystemResourceServletContextResourceInputStreamResourceByteArrayResourceResourceLoader内容结构体系源码分析ResourcePatternResolver内容容器…

gdb调试插件的安装——gef/gdbinit/peda(记录向)

源地址:https://github.com/hugsy/ 根据上面的要求: gdb必须得8.0以上,python得3.6以上,但是一般裸机的gdb都是7.2,python是2.7。我们需要下载更高版本的gdb和python 先将系统自带的gdb删除: sudo yum r…