Java --- JVM的执行引擎

目录

一、执行引擎概述 

1.1、执行引擎的工作过程

二、Java代码编译和执行的过程

三、解释器

 3.1、解释器工作机制

3.2、解释器分类

3.3、解释器现状

四、JIT编译器

五、热点代码及探测方式

六、方法调用计数器

 6.1、热点衰减

七、回边计数器

八、HotSpot VM设置程序执行方式

8.1、HotSpot VM中JIT分类

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

8.2.1、分层编译策略


一、执行引擎概述 

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

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

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

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

1.1、执行引擎的工作过程

1、执行引擎在执行的过程中究竟需要执行什么样的字节码指令完全依赖于PC寄存器。

2、每当执行完一项指令操作后,PC寄存器就会更新下一条需要被执行的指令地址。

3、当然方法在执行的过程中,执行引擎有可能会通过存储在局部变量表中的对象引用准确定位到存储在Java堆区中的对象实例信息,以及通过对象头中的元数据指针定位到目标对象的类型信息。

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

二、Java代码编译和执行的过程

 大部分的程序代码转换成物理机的目标代码或虚拟机能执行的指令集之前,都需要经过上图中的各个步骤。

Java代码编译是由Java源码编译器来完成。

Java字节码的执行是由JVM执行引擎来完成。

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

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

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

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

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

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

三、解释器

JVM设计者们的初衷仅仅只是单纯地为了满足Java程序实现跨平台特性,因此避免采用静态编译的方式直接生成本地机器指令,从而诞生了实现解释器在运行时采用逐行解释字节码执行程序的想法。

 3.1、解释器工作机制

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

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

3.2、解释器分类

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

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

而模板解释器将每一条字节码和一个模板函数相关联,模板函数中直接产生这条字节码执行时的机器码,从而很大程度上提高了解释器的性能。

在HotSpot VM中,解释器主要由Interpreter模块和Ctode模块构成。

     Interpreter模块:实现了解释器的核心功能

     Code模块:用于管理HotSpot VM在运行时生成的本地机器指令

3.3、解释器现状

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

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

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

四、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程序的执行性能。

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

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

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

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

    ①、方法调用计数器用于统计方法的调用次数。

    ②、回边计数器则用于统计循环体执行的循环次数。

六、方法调用计数器

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

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

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

 

 6.1、热点衰减

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

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

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

七、回边计数器

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

八、HotSpot VM设置程序执行方式

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

①、-Xint:完全采用解释器模式执行程序;

②、-Xcomp:完全采用即时编译器模式执行程序。如果即时编译出现问题,解释器会介入执行。

③、-Xmixed:采用解释器+即时编译器的混合模式共同执行程序。

参考代码:

public class IntCompTest {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        testPrimeNumber(1000000);
        long end = System.currentTimeMillis();
        //-Xint:11740ms -Xcomp:446ms -Xmixed:438ms
        System.out.println("花费的时间为:" + (end - start));
    }
    public static void testPrimeNumber(int count){
        for (int i = 0; i < count; i++) {
            //计算100以内的质数
            for (int j = 2; j <= 100 ; j++) {
                for (int k = 2; k <= Math.sqrt(j); k++) {
                    if (j % k == 0){
                        continue;
                    }
                }
            }
        }
    }
}

8.1、HotSpot VM中JIT分类

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

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

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

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

1、在不同的编译器上有不同的优化策略,C1编译器上主要有方法内联,去虚拟化、冗余消除。

    ①、方法内联:将引用的函数代码编译到引用点处,这样可以减少栈帧的生成,减少参数传递以及跳转过程。

    ②、去虚拟化:对唯一的实现类进行内联。

    ③、冗余消除:在运行期间把一些不会执行的代码折叠掉。

2、C2的优化主要是在全局层面,逃逸分析是优化的基础。基于逃逸分析在C2上有如下几种优化:

    ①、标量替换:用标量值代替聚合对象的属性值

    ②、栈上分配:对于未逃逸的对象分配对象在栈而不是在堆。

    ③、同步消除:消除同步操作,通常指synchronized

8.2.1、分层编译策略

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

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

总结:1、一般情况下,JIT编译出来的机器码性能比解释器高。2、C2编译器启动时长比C1编译器慢,系统稳定执行以后,C2编译器执行速度远远快于C1编译器。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用python随机生成座位表

1 问题 学习中总会遇到大大小小的考试&#xff0c;考试场地和考试座位的确立是考试准备工作的重要一环&#xff0c;那么能否用python随机生成座位表呢。 2 方法 定义座位表的行列数&#xff0c;例如10行10列创建一个二维数组&#xff0c;用于存储座位信息&#xff0c;例如使用0…

【KVM】硬件虚拟化技术(详)

前言 大家好&#xff0c;我是秋意零。 经过前面章节的介绍&#xff0c;已经知道KVM虚拟化必须依赖于硬件辅助的虚拟化技术&#xff0c;本节就来介绍一下硬件虚拟化技术。 &#x1f47f; 简介 &#x1f3e0; 个人主页&#xff1a; 秋意零&#x1f525; 账号&#xff1a;全平…

Android Studio真机运行时提示“安装失败”

用中兴手机真机运行没问题&#xff0c;用Vivo运行就提示安装失败。前提&#xff0c;手机已经打开了调试模式。 报错 Android Studio报错提示&#xff1a; Error running app The application could not be installed: INSTALL_FAILED_TEST_ONLY 手机报错提示&#xff1a; 修…

基于SSM框架的高校试题管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

Ps:RGB 颜色模式

Ps菜单&#xff1a;图像/模式/RGB 颜色 Image/Mode/RGB Color RGB 颜色模式 RGB Color Mode是数字图像捕捉、处理以及显示的最常用模式&#xff0c;也是 Photoshop 默认的工作模式。 RGB 是 Red&#xff08;红色&#xff09;、Green&#xff08;绿色&#xff09;、Blue&#xf…

触摸屏【威纶通】

威纶通&#xff1a; cMT-FHDX-920编程软件&#xff1a; EBproV6.08.02.500_20230828 新建工程&#xff1a; 文件》新建 常用》系统参数 新增设备服务 编程&#xff1a; 目录树》11》新增常用》元件 按钮 标签&#xff1a; 文本信息

【Nginx】nginx | 微信小程序验证域名配置

【Nginx】nginx | 微信小程序验证域名配置 一、说明二、域名管理 一、说明 小程序需要添加头条的功能&#xff0c;内容涉及到富文本内容显示图片资源存储在minio中&#xff0c;域名访问。微信小程序需要验证才能显示。 二、域名管理 服务器是阿里云&#xff0c;用的宝塔管理…

pta 装箱问题 Python3

假设有N项物品&#xff0c;大小分别为s1​、s2​、…、si​、…、sN​&#xff0c;其中si​为满足1≤si​≤100的整数。要把这些物品装入到容量为100的一批箱子&#xff08;序号1-N&#xff09;中。装箱方法是&#xff1a;对每项物品, 顺序扫描箱子&#xff0c;把该物品放入足以…

解决VSCode中文乱码问题

解决VSCode乱码问题 1.问题描述&#xff1a;2.原因分析&#xff1a;3.解决方案&#xff1a;1&#xff09;解决步骤2&#xff09;深入分析 4.总结 1.问题描述&#xff1a; 最近用vscode的时候突然发现中文字符出现乱码。在网上找了好几种方法都不行&#xff0c;用各种编码格式打…

排序 算法(第4版)

本博客参考算法&#xff08;第4版&#xff09;&#xff1a;算法&#xff08;第4版&#xff09; - LeetBook - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台 本文用Java实现相关算法。 我们关注的主要对象是重新排列数组元素的算法&#xff0c;其中每个元素…

阿里云国际站:云备份

文章目录 一、阿里云云备份的概念 二、云备份的优势 三、云备份的功能 四、云备份的应用场景 一、阿里云云备份的概念 云备份作为阿里云统一灾备平台&#xff0c;是一种简单易用、敏捷高效、安全可靠的公共云数据管理服务&#xff0c;可以为阿里云ECS整机、ECS数据库、文件…

Linux 之 MakeFile

MakeFile 前言MakeFile基本介绍MakeFile介绍MakeFile文件命名Makefile编写规则MakeFile的执行步骤 MakeFilemakefile组成元素makefile显示规则makefile隐晦规则伪目标(标签与文件冲突问题) makefile变量定义makefile中的运算符和特殊变量 makefile文件指示makefile注释 makefil…

【刷题篇】动态规划(四)

文章目录 1、珠宝的最高价值2、下降路径最小和3、最小路径和4、地下城游戏5、按摩师6、打家劫舍|| 1、珠宝的最高价值 现有一个记作二维矩阵 frame 的珠宝架&#xff0c;其中 frame[i][j] 为该位置珠宝的价值。拿取珠宝的规则为&#xff1a; 只能从架子的左上角开始拿珠宝 每次…

数据结构 | 带头双向循环链表专题

数据结构 | 带头双向循环链表专题 前言 前面我们学了单链表&#xff0c;我们这次来看一个专题带头的双向循环链表~~ 文章目录 数据结构 | 带头双向循环链表专题前言带头双向循环链表的结构实现双向链表头文件的定义哨兵位初始化创建节点尾插尾删头插头删打印查找指定位置前插入…

CentOS指令学习

目录 一、常用命令 1、ls 2、cd_pwd 3、touch_mkdir_rmdir_rm 4、cp_mv 5、whereis_which_PATH 6、find 7、grep 8、man_help 9、关机与重启 二、压缩解压 1、zip_unzip 2、gzip_gunzip 3、tar 三、其他指令 1、查看用户登录信息 2、磁盘使用情况 3、查看文件…

Java15新增特性

前言 前面的文章&#xff0c;我们对Java9、Java10、Java11、Java12 、Java13、Java14 的特性进行了介绍&#xff0c;对应的文章如下 Java9新增特性 Java10新增特性 Java11新增特性 Java12新增特性 Java13新增特性 Java14新增特性 今天我们来一起看一下Java15这个版本的一些重要…

74HC165 并入串出

/******************************************************** 程序名&#xff1a;main.C 版 本&#xff1a;Ver1.0 芯 片&#xff1a;AT89C51或STC89C51 晶 体&#xff1a;片外12MHz 编 程: Joey 日 期&#xff1a;2023-11-13 描 述&#xff1a;通过 74HC165 对 16 按键…

android 10车载桌面ActivityView触摸事件源码详解分析

hi&#xff0c;粉丝朋友们&#xff1a; 背景 大家好&#xff01;近来居然有好几个粉丝朋友居然问到了一个虚拟屏幕触摸相关的问题&#xff0c;还有老版本android 10上面有个车载桌面使用的ActivityView可以正常触摸的问题。 其实这个ActivityView在最新的版本已经没有了&…

视觉大模型DINOv2:自我监督学习的新领域

1 DINOv2 1.1 DINOv2特点 前段时间&#xff0c;Meta AI 高调发布了 Segment Anything&#xff08;SAM&#xff09;&#xff0c;SAM 以交互式方式快速生成 Mask&#xff0c;并可以对从未训练过的图片进行精准分割&#xff0c;可以根据文字提示或使用者点击进而圈出图像中的特定…

基于springboot实现结合疫情情况的婚恋系统【项目源码】

基于springboot实现结合疫情情况的婚恋系统演示 SpringBoot框架 SpringBoot是一个全新开源的轻量级框架。基于Spring4.0设计&#xff0c;其不仅继承了Spring框架原来有的优秀特性&#xff0c;而且还通过简化配置文件来进一步简化了Spring应用的整个搭建以及开发过程。另外在原…