【JVM详解四】执行引擎
一、概述
Java程序运行时,JVM会加载.class字节码文件,但是字节码并不能直接运行在操作系统之上,而JVM中的执行引擎就是负责将字节码转化为对应平台的机器码让CPU运行的组件。
执行引擎是JVM核心的组成部分之一。可以把JVM架构分成三部分,如下图所示:
执行引擎位于JVM的最下层(图中虚线框部分),可以粗略地看到执行引擎负责和运行时数据区交互。
二、计算机语言的发展史
在讲解执行引擎之前,需要知道什么是机器码、汇编语言、高级语言以及为什么会有Java字节码的出现。
2.1 机器码
各种用 0 和 1 组成的二进制编码方式表示的指令,叫作机器指令码,简称机器码。
计算机发展的初始阶段,人们就用机器码编写程序,我们也称为机器语言。机器语言虽然能够被计算机理解和接受,但由于可读性差不便于人类读写,并且用它编程容易出差错。使用机器码编写的程序一经输入计算机,CPU可以直接读取运行,因此和其他语言编的程序相比,执行速度最快。机器码与CPU紧密相关,所以不同种类的CPU所对应的机器码也就不同。
2.2 汇编语言
由于机器码是由0和1组成的二进制序列,可读性实在太差,于是人们发明了指令。
指令就是把机器码中特定的0和1序列,简化成对应的指令(一般为英文简写,如mov、inc等),可读性稍好,这就是我们常说的汇编语言。在汇编语言中,用助记符 (Mnemonics) 代替机器码的操作码,用地址符号 (Symbol) 或标号 (Label) 代替指令或操作数的地址。
不同的硬件平台,各自支持的指令是有差别的。因此每个平台所支持的指令,称为对应平台的指令集,如常见的x86指令集对应的是x86架构的平台,ARM指令集对应的是ARM架构的平台。不同平台之间指令不可以直接移植。
由于计算机只认识机器码,所以用汇编语言编写的程序还必须经过汇编器转换为机器语言,计算机才能识别和执行。
2.3 高级语言
为了使计算机用户编程序更容易些,后来就出现了各种高级计算机语言。比如C、C++等更容易让人识别的语言。
高级语言则相对汇编语言更易于编写,有更好的可读性,一般编译器会将高级语言转换成汇编语言,然后再由汇编器转换为机器指令由计算机执行。
2.4 字节码
字节码是一种中间状态(中间码)的二进制代码(文件),需要转译后才能成为机器码。Java 程序可以通过编译器将源码编译成 Java 字节码,特定平台上的虚拟机将字节码转译为可以直接执行的指令,也就实现了跨平台性。如下图所示:
三、执行引擎工作过程
- 执行引擎在执行过程中,需要执行什么样的字节码指令取决于PC寄存器(程序计数器);
- 每执行完一项指令操作之后,PC寄存器会更新下一条需要执行的指令地址;
- 方法执行过程中,执行引擎可能会通过局部变量表中的对象引用准确定位到 Java 堆中的对象实例信息,以及通过对象头中的元数据信息定位到目标对象的类型信息。
- 解释器
- JIT编译器
- 垃圾收集器
3.1 解释器
解释器就是一个运行时的“翻译者”,将字节码指令翻译为对应平台的本地机器指令由CPU执行,当一条指令执行完成后再根据PC寄存器中记录的下一条指令执行解释操作。
JVM设计者的初衷是为了满足Java程序实现跨平台特性,因此避免采用静态编译的方式直接生成机器码,从而诞生了实现解释器在运行时采用逐行解释字节码执行程序的想法。
3.2 JIT(Just-In-Time)编译器
当执行某些频繁被调用的代码(比如for循环中的代码)时,如果按照解释执行,效率非常低,这种被频繁调用的代码成为热点代码。为了提高热点代码的执行效率,在运行时,JIT编译器则会将这些代码编译成与本地平台有关的机器码,并进行各种层次的优化。
JIT的构成组件包括:
- 中间代码生成器——生成中间代码
- 代码优化器——优化中间代码
- 目标代码生成器——生成机器码或本地代码
- 分析器——负责查找热点代码
3.2.1 JIT编译器类型
在 Hotspot 虚拟机中内置了两种JIT编译器:
- C1编译器:主要关注点在于局部性能优化,适用于执行时间短或对启动性能有要求的程序,如:GUI应用,C1编译器也被称为Client Compiler。
- C2编译器:为长期运行的服务端应用程序做性能优化的编译器,适用于执行时间较长或对峰值性能有要求的程序,C2编译器也被称为Server Compiler。
3.2.2 分层编译
在 Java7 引入了分层编译,这种方式综合了 C1 的启动优势和 C2 的峰值性能优势。分层编译将 JVM 的执行状态分为5个层次:
- 第0层:程序解释执行,默认开启性能监控(Profiling),如果不开启,可触发第二层编译
- 第1层:C1编译,将字节码编译成本地代码,进行简单可靠的优化,不开启Profiling
- 第2层:C1编译,开启Profiling,仅执行带方法调用次数和循环回边执行次数Profiling的C1编译
- 第3层:C1编译,执行所有带Profiling的C1编译
- 第4层:C2编译,将字节码编译为本地代码,但会启用一下编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。
Java8 中默认开启分层编译,-XX:-TieredCompilation 参数可关闭分层编译只使用C2编译,如果只使用C1编译可设置参数 -XX:TieredStopAtLevel=1。
-Xint参数可设置为强制解释器模式运行,-Xcomp可设置为强制运行JIT编译模式。
3.2.3 热点代码探测
Hotspot 虚拟机判定热点代码基于2种计数器进行,方法调用计数器和回边计数器,只有代码符合标准并达到设置的阈值才会进行JIT编译优化。
1)方法调用计数器
当某个方法调用次数达到阈值就会触发JIT编译优化。
jinfo -flag CompileThreshold 或者 java -XX:+PrintFlagsFinal -version 命令可查看方法调用次数阈值,客户端模式下默认值为1500,服务端模式下默认值为10000。
2)回边计数器
用于统计方法体中循环体代码执行次数,字节码中遇到控制流向后跳转的指令称为“回边”(Back Edge),用于计算是否为热点代码的阈值。
计算公式如下:
回边计数器阈值 = 方法调用计数器阈值(CompileThreshold)*(OSR比率(OnStackReplacePercentage)-解释器监控比例(InterpreterProfilePercentage))/ 100
java -XX:+PrintFlagsFinal -version 命令可查看相关参数
根据图中显示的各参数的默认值可以计算出回边计数器阈值为:1000 * (140 - 33) = 10700
3.2.4 编译优化技术
1)方法内联
方法内联的优化行为是将目标方法的代码复制到发起调用的方法中,避免真实方法调用。
private int add(int a, int b, int c, int d) {return addInt1(a, b) + addInt2(c, d);
}
private int addInt1(int a, int b) {return a + b;
}
private int addInt2(int a, int b) {return a + b;
}
例如上面的代码如果被检测为热点代码,则会被优化为以下代码:
private int add(int a, int b, int c, int d) {return a + b + c + d;
}
热点方法不一定都会被内联优化,只有当方法体大小小于参数 -XX:FreqInlineSize 值(默认325字节)才会进行内联,非热点方法当方法体小于参数 -XX:MaxInlineSize 值(默认35字节)才会进行内联。
相关性能调优 :
- 减小热点方法检测阈值,增加内联方法体阈值,缺点则是会增加内存占用
- 尽量避免在一个方法体内写入大量代码,习惯使用小方法体
- 尽量使用final private static 关键字修饰方法,代码优化时,因为继承需要额外的类型检查。
2)锁消除
当方法中的局部方法中创建的对象只能被当前线程访问时,不存在锁竞争,JIT编译会对这个对象的方法进行锁消除。
参数 -XX:+EliminateLocks 可以开启锁消除(默认开启),-XX:-EliminateLocks 则是关闭锁消除。
3)锁粗化
如果检测到同一个对象执行了连续的加锁和解锁操作,则会将这一系列操作合并成一个更大的锁,从而提升程序运行效率。
4)逃逸分析
JIT编译器会对热点代码中的对象进行逃逸分析,分析该对象动态作用域,当被传递到其他方法中称为方法逃逸,当能被外部方法所引用则为线程逃逸。
不逃逸 到 方法逃逸 再到 线程逃逸,逃逸程度由低到高。
逃逸分析可以通过参数 -XX:+DoEscapeAnalysis开启(jdk1.8默认开启),或 -XX:-DoEscapeAnalysis 关闭。
关闭逃逸分析会导致对象分配到堆中,频繁触发垃圾回收导致代码运行慢。
5)标量替换
当确定对象不会逃逸出线程之外,该对象则会被分配到栈上,对象分配到栈需要进行成员变量拆分,这种优化技术叫做标量替换。标量替换需要开启逃逸分析。
标量替换可以通过参数 -XX:+EliminateAllocations开启(jdk1.8默认开启),或-XX:+EliminateAllocations关闭
3.3 垃圾收集器
Java的一个主要特点就是开发人员不需要过分关注对象的内存管理,无用对象的销毁和空间释放都交由JVM的垃圾收集器处理。这减轻了编程负担提高了编程效率,但垃圾回收也会影响程序的性能。
详细介绍见上章。
四、总结
JVM中的执行引擎是JVM的重要组成部分之一,主要负责将字节码指令翻译成机器码指令。
执行引擎包括解释器,JIT解释器和垃圾收集器。
解释器就是运行时的“翻译者”,将字节码解释为机器指令。
但是某些频繁执行的热点代码依然采用解释执行的话会导致程序执行很慢,JIT编译器则是负责将热点代码编译分层优化成本地机器码。
垃圾收集器则负责无用对象的销毁,释放内存空间。
相关文章:
【JVM详解四】执行引擎
一、概述 Java程序运行时,JVM会加载.class字节码文件,但是字节码并不能直接运行在操作系统之上,而JVM中的执行引擎就是负责将字节码转化为对应平台的机器码让CPU运行的组件。 执行引擎是JVM核心的组成部分之一。可以把JVM架构分成三部分&am…...
route 与 router 之间的差别
简述: router:主要用于处理一些动作, route:主要获得或处理一些数据,比如地址、参数等 例: videoInfo1.vue: <template><div class"video-info"><h3>二级组件…...
[vue3] Ref Reactive
【b站-【前端面试】Vue3 ref 与 reactive 区别】 Ref:Ref用于创建一个响应式的基本数据类型,比如数字、字符串等。它将普通的数据变成响应式数据,可以监听数据的变化。使用Ref时,我们可以通过.value来访问和修改数据的值。 Reac…...
SamWaf开源轻量级的网站应用防火墙(安装包),私有化部署,加密本地存储的数据,易于启动,并支持 Linux 和 Windows 64 位和 Arm64
一、SamWaf轻量级开源防火墙介绍 (文末提供下载) SamWaf网站防火墙是一款适用于小公司、工作室和个人网站的开源轻量级网站防火墙,完全私有化部署,数据加密且仅保存本地,一键启动,支持Linux,Wi…...
极客说|利用 Azure AI Agent Service 创建自定义 VS Code Chat participant
作者:卢建晖 - 微软高级云技术布道师 「极客说」 是一档专注 AI 时代开发者分享的专栏,我们邀请来自微软以及技术社区专家,带来最前沿的技术干货与实践经验。在这里,您将看到深度教程、最佳实践和创新解决方案。关注「极客说」&a…...
22.2、Apache安全分析与增强
目录 Apache Web安全分析与增强 - Apache Web概述Apache Web安全分析与增强 - Apache Web安全威胁Apache Web安全机制Apache Web安全增强 Apache Web安全分析与增强 - Apache Web概述 阿帕奇是一个用于搭建WEB服务器的应用程序,它是开源的,它的配置文件…...
理邦仪器嵌入式(C/C++开发)开发面试题及参考答案
C++ 虚函数的概念和作用 C++ 中的虚函数是一种非常重要的机制,它在实现多态性方面起着关键作用。 概念上来说,虚函数是在基类中使用关键字 virtual 声明的成员函数。当基类的指针或引用指向派生类的对象时,通过这个基类的指针或引用调用虚函数,实际执行的是派生类中重写的该…...
windows + visual studio 2019 使用cmake 编译构建静、动态库并调用详解
环境 windows visual studio 2019 visual studio 2019创建cmake工程 1. 静态库.lib 1.1 静态库编译生成 以下是我创建的cmake工程文件结构,只关注高亮文件夹部分 libout 存放编译生成的.lib文件libsrc 存放编译用的源代码和头文件CMakeLists.txt 此次编译CMak…...
Chrome 浏览器 支持多账号登录和管理的浏览器容器解决方案
根据搜索结果,目前没有直接提到名为“chrometable”的浏览器容器或插件。不过,从功能描述来看,您可能需要的是一个能够支持多账号登录和管理的浏览器容器解决方案。以下是一些可能的实现方式: 1. 使用 Docker 容器化部署 Chrome …...
GrassWebProxy
GrassWebProxy第一版: using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; using System.IO; using Newtonsoft.Json;…...
DeepSeek API 调用 - Spring Boot 实现
DeepSeek API 调用 - Spring Boot 实现 1. 项目依赖 在 pom.xml 中添加以下依赖: <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></depe…...
【DeepSeek】Deepseek辅组编程-通过卫星轨道计算终端距离、相对速度和多普勒频移
引言 笔者在前面的文章中,介绍了基于卫星轨道参数如何计算终端和卫星的距离,相对速度和多普勒频移。 【一文读懂】卫星轨道的轨道参数(六根数)和位置速度矢量转换及其在终端距离、相对速度和多普勒频移计算中的应用 Matlab程序 …...
【kafka实战】05 Kafka消费者消费消息过程源码剖析
1. 概述 Kafka消费者(Consumer)是Kafka系统中负责从Kafka集群中拉取消息的客户端组件。消费者消费消息的过程涉及多个步骤,包括消费者组的协调、分区分配、消息拉取、消息处理等。本文将深入剖析Kafka消费者消费消息的源码,并结合…...
[EAI-033] SFT 记忆,RL 泛化,LLM和VLM的消融研究
Paper Card 论文标题:SFT Memorizes, RL Generalizes: A Comparative Study of Foundation Model Post-training 论文作者:Tianzhe Chu, Yuexiang Zhai, Jihan Yang, Shengbang Tong, Saining Xie, Dale Schuurmans, Quoc V. Le, Sergey Levine, Yi Ma 论…...
算法与数据结构(字符串相乘)
题目 思路 这道题我们可以使用竖式乘法,从右往左遍历每个乘数,将其相乘,并且把乘完的数记录在nums数组中,然后再进行进位运算,将同一列的数进行相加,进位。 解题过程 首先求出两个数组的长度,…...
DeepSeek从入门到精通:全面掌握AI大模型的核心能力
文章目录 一、DeepSeek是什么?性能对齐OpenAI-o1正式版 二、Deepseek可以做什么?能力图谱文本生成自然语言理解与分析编程与代码相关常规绘图 三、如何使用DeepSeek?四、DeepSeek从入门到精通推理模型推理大模型非推理大模型 快思慢想&#x…...
【Pytorch函数】PyTorch随机数生成全解析 | torch.rand()家族函数使用指南
🌟 PyTorch随机数生成全解析 | torch.rand()家族函数使用指南 🌟 📌 一、核心函数参数详解 PyTorch提供多种随机数生成函数(注意:无直接torch.random()函数),以下是常用函数及参数:…...
vue print 打印
vue 点击打印页面部分内容,或者打印弹窗内的内容 打印页面部分内容 <template><div><div id"print"><div class"info"><div class"bx_title">费用报销单<span class"code">NO.<s…...
【异常解决】在idea中提示 hutool 提示 HttpResponse used withoud try-with-resources statement
博主介绍:✌全网粉丝22W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
【Uniapp-Vue3】UniCloud云数据库获取指定字段的数据
使用where方法可以获取指定的字段: let db uniCloud.database(); db.collection("数据表").where({字段名1:数据, 字段名2:数据}).get({getOne:true}) 如果我们不在get中添加{getOne:true},在只获取到一个数据res.result.data将会是一个数组&…...
信息科技伦理与道德3-2:智能决策
2.2 智能推荐 推荐算法介绍 推荐系统:猜你喜欢 https://blog.csdn.net/search_129_hr/article/details/120468187 推荐系统–矩阵分解 https://blog.csdn.net/search_129_hr/article/details/121598087 案例一:YouTube推荐算法向儿童推荐不适宜视频 …...
openssl使用
openssl使用 提取密钥对 数字证书pfx包含公钥和私钥,而cer证书只包含公钥。提取需输入证书保护密码 openssl pkcs12 -in xxx.pfx -nocerts -nodes -out pare.key提取私钥 openssl rsa -in pare.key -out pri.key提取公钥 openssl rsa -in pare.key -pubout -ou…...
Visual Studio 2022 中使用 Google Test
要在 Visual Studio 2022 中使用 Google Test (gtest),可以按照以下步骤进行: 安装 Google Test:确保你已经安装了 Google Test。如果没有安装,可以通过 Visual Studio Installer 安装。在安装程序中,找到并选择 Googl…...
SpringBoot3 + Jedis5 + Redis集群 如何通过scan方法分页获取所有keys
背景: 由于需要升级老项目代码,从SpringBoot1.5.x 升级到 SpringBoot3.3.x,框架中引用的Jedis自动升级到了 5.x;正好代码中有需要获取Redis集群的所有keys的需求存在;代码就不适用了,修改如下: POM 由于…...
WGCLOUD监控系统部署教程
官网地址:下载WGCLOUD安装包 - WGCLOUD官网 第一步、环境配置 #安装jdk 1、安装 EPEL 仓库: sudo yum install -y epel-release 2、安装 OpenJDK 11: sudo yum install java-11-openjdk-devel 3、如果成功,你可以通过运行 java …...
协议-WebRTC-HLS
是什么? WebRTC(Web Real-Time Communication) 实现 Web 浏览器和移动应用程序之间通过互联网直接进行实时通信。允许点对点音频、视频和数据共享,而无需任何插件或其他软件。WebRTC 广泛用于构建视频会议、语音通话、直播、在线游…...
jQuery UI 下载指南
jQuery UI 下载指南 引言 jQuery UI 是一个基于 jQuery 的用户界面和交互库,它提供了一套丰富的交互组件和视觉效果,可以帮助开发者快速构建美观、交互性强的网页应用。本文将为您详细介绍如何下载 jQuery UI,并指导您进行安装和使用。 jQ…...
MySQL系列之数据类型(String)
导览 前言一、字符串类型知多少 1. 类型说明2. 字符和字节的转换 二、字符串类型的异同 1. CHAR & VARCHAR2. BINARY & VARBINARY3. BLOB & TEXT4. ENUM & SET 结语精彩回放 前言 MySQL数据类型第三弹闪亮登场,欢迎关注O。 本篇博主开始谈谈MySQ…...
Kotlin 2.1.0 入门教程(十)if、when
if 表达式 if 是一个表达式,它会返回一个值。 不存在三元运算符(condition ? then : else),因为 if 在这种场景下完全可以胜任。 var max aif (a < b) max bif (a > b) {max a } else {max b }max if (a > b) a…...
编程式路由
<script> export default {name: video-Info1,created () {setTimeout(() > {this.$router.push({ name: home })}, 3000)} } </script> 编程式路由:实现 不需要用户点击router-link,由代码实现路由跳转。 应用场景:用户登录…...
