深入浅出JVM(七)之执行引擎的解释执行与编译执行

本篇文章围绕执行引擎,深入浅出的解析执行引擎中解释器与编译器的解释执行和编译执行、执行引擎的执行方式、逃逸分析带来的栈上分配、锁消除、标量替换等优化以及即时编译器编译对热点代码的探测

执行引擎

hotspot执行引擎结构图

执行引擎分为解释器、JIT即时编译器以及垃圾收集器

执行引擎通过解释器/即时编译器将字节码指令解释/编译为对应OS上的的机器指令

image-20210430191033833.png

本篇文章主要围绕解释器与即时编译器,垃圾收集器将在后续文章解析

解释执行与编译执行

Java虚拟机执行引擎在执行Java代码时,会有两种选择:解释执行和编译执行

解释执行:通过字节码解释器把字节码解析为机器语言执行

编译执行:通过即时编译器产生本地代码执行

Class文件中的代码到底是解释执行还是编译执行只有Java虚拟机自己才能判断准确

编译过程

image-20201113160400365.png

编译流程在前一篇文章深入浅出JVM之前端编译过程与语法糖原理已经说明,在本篇文章中不再概述

经典编译原理: 1.对源码进行词法,语法分析处理 2.把源码转换为抽象语法树

javac编译器完成了对源码进行词法,语法分析处理为抽象语法树,再遍历抽象语法树生成线性字节码指令流的过程

剩下的指令流有两种方式执行

  1. 由虚拟机内部的字节码解释器去将字节码指令进行逐行解释 (解释执行)
  2. 或优化器(即时编译器)优化代码最后生成目标代码 (编译执行)

执行引擎流程图

image-20210430150736000.png

解释器与编译器

解释器

作用: 对字节码指令逐行解释

优点: 程序启动,解释器立即解释执行

缺点: 低效

即时编译器 (just in time compiler)

Java中的"编译期"不确定

  • 可能说的是执行javac指令时的前端编译器 (.java->.class)
  • 也可能是后端编译器JIT (字节指令->机器指令)
  • 还可能是AOT编译器(静态提前编译器) (.java->机器指令)

作用: 将方法编译成机器码缓存到方法区,每次调用该方法执行编译后的机器码

优点: 即时编译器把代码编译成本地机器码,执行效率高,高效

缺点: 程序启动时,需要先编译再执行

执行引擎执行方式

执行引擎执行方式大致分为3种

-Xint: 完全采用解释器执行

-Xcomp: 优先采用即时编译器执行,解释器是后备选择

-Xmixed: 采用解释器 + 即时编译器

image-20210430194043245.png

hotspot中有两种JIT即时编译器

Client模式下的C1编译器:简单优化,耗时短(C1优化策略:方法内联,去虚拟化,冗余消除)

Server模式下的C2编译器:深度优化,耗时长 (C2主要是逃逸分析的优化:标量替换,锁消除,栈上分配)

分层编译策略:程序解释执行(不开启逃逸分析)可以触发C1编译,开启逃逸分析可以触发C2编译

解释器,C1,C2编译器同时工作,热点代码可能被编译多次

解释器在程序刚刚开始的时候解释执行,不需要承担监控的开销

C1有着更快的编译速度,能为C2编译优化争取更多时间

C2用高复杂度算法,编译优化程度很高的代码

逃逸分析带来的优化

当对象作用域只在某个方法时,不会被外界调用到,那么这个对象就不会发生逃逸

开启逃逸分析后,会分析对象是否发生逃逸,当不能发生逃逸时会进行栈上分配、锁消除、标量替换等优化

栈上分配内存
 //-Xms1G -Xmx1G -XX:+PrintGCDetails public class StackMemory {public static void main(String[] args) {long start = System.currentTimeMillis();​for (int i = 0; i < 10000000; i++) {memory();}​System.out.println("花费时间:"+(System.currentTimeMillis()-start)+"ms");​try {TimeUnit.SECONDS.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}​private static void memory(){StackMemory memory = new StackMemory();}}

-XX:-DoEscapeAnalysis 花费时间:63ms (未开启逃逸分析)

-XX:+DoEscapeAnalysis 花费时间:4ms (开启逃逸分析)

默认开启逃逸分析

锁消除

同步加锁会带来开销

锁消除:当加锁对象只作用某个方法时,JIT编译器借助逃逸分析判断使用的锁对象是不是只能被一个线程访问,如果是这种情况下就不需要同步,可以取消这部分代码的同步,提高并发性能

标量替换

标量: 无法再分解的数据 (基本数据类型)

聚合量: 还可以再分解的数据 (对象)

标量替换: JIT借助逃逸分析,该对象不发生逃逸,只作用于某个方法会把该对象(聚合量)拆成若干个成员变量(标量)来代替

默认开启标量替换

 public class ScalarSubstitution {static class Man{int age;int id;​public Man() {}}​public static void createInstance(){Man man = new Man();man.id = 123;man.age = 321;}public static void main(String[] args) {long start = System.currentTimeMillis();​for (int i = 0; i < 10000000; i++) {createInstance();}​System.out.println("花费时间:"+(System.currentTimeMillis()-start)+"ms");​try {TimeUnit.SECONDS.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
 //-Xmx200m -Xms200m -XX:+PrintGCDetails //-XX:+DoEscapeAnalysis 设置开启逃逸分析//-XX:-EliminateAllocations 设置不开启标量替换 //开启逃逸分析 + 关闭标量替换 : 花费时间:93ms//开启逃逸分析 + 开启标量替换  : 花费时间:6ms

热点代码与热点探测

JIT编译器并不是编译所有的字节码,JIT编译器只编译热点代码

热点代码: 被多次调用的方法 或 方法中多次循环的循环体

栈上替换(OSR): JIT将方法中的热点代码编译为本地机器指令(被多次执行的循环体)

编译对象都是方法,如果是栈上替换则"入口"在方法的循环体开始那里

热点探测功能决定了被调用多少次的方法能成为热点代码

hotspot采用基于计数器的热点探测

  • 方法调用计数器 : 统计方法调用次数
  • 回边计数器 : 统计循环体执行循环次数

方法调用时先判断是否有执行编译后的机器码,有则直接使用方法区的Code cache中的机器码;没有机器码则判断计数器次数是否超过阈值,超过则触发编译,编译后机器码存储在方法区Code cache中使用;最后都没有就使用解释执行

总结

本篇文章将围绕执行引擎,深入浅出的解析执行引擎中的解释器、即时编译器各自执行的优缺点以及原理

执行引擎由解释器、即时编译器、垃圾收集器构成,默认情况下使用解释器与编译器的混合方式执行

即时编译器分为C1、C2编译器,其中C1编译快但优化小,C2开启逃逸分析使用栈上分配、锁消除、标量替换进行优化,编译耗时但是优化大

即时编译器并不是所有代码都编译,而是使用方法技术和循环计数来将热点代码编译成机器码存放在方法区的Code Cache中

在混合执行的模式下,解释器、C1、C2编译器同时工作,分层编译

最后(一键三连求求拉~)

本篇文章笔记以及案例被收入 gitee-StudyJava、 github-StudyJava 感兴趣的同学可以stat下持续关注喔~

有什么问题可以在评论区交流,如果觉得菜菜写的不错,可以点赞、关注、收藏支持一下~

关注菜菜,分享更多干货,公众号:菜菜的后端私房菜

本文由博客一文多发平台 OpenWrite 发布!

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

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

相关文章

QT_day4

1.思维导图 2. 输入闹钟时间格式是小时:分钟 widget.cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);id startTimer(1000);flag1;speecher new QTextT…

做抖音小店怎么选品?给新手商家的三条建议,能让你销量猛增999+

大家好&#xff0c;我是电商花花。 总是担心店铺不出单&#xff0c;没有销量&#xff0c;看着断断续续的收益&#xff0c;新手商家应该都是愁容满面吧。 今天花花从是3个维度上给新手商家一些建议&#xff0c;讲解一下如何高效选品&#xff0c;加你如何让你出单猛增999。 以前…

训练Sora模型,你可能需要这些开源代码,模型,数据集及算力评估

在之前的文章&#xff0c;我们总结了Sora模型上用到的一些核心技术和论文 复刻大模型 Sora 有多难&#xff1f;一张图带你读懂 Sora 的技术路径一文看懂大模型 Sora 技术推演 今天这篇文章来自我们社区讨论交流&#xff0c;我这边整理和总结现有的一些开源代码、模型、数据集…

【大数据】Flink 内存管理(一):设置 Flink 进程内存

Flink 内存管理&#xff08;一&#xff09;&#xff1a;设置 Flink 进程内存 1.配置 Total Memory2.JVM 参数3.根据比例限制的组件&#xff08;Capped Fractionated Components&#xff09; Apache Flink 通过严格控制各种组件的内存使用&#xff0c;在 JVM 上提供高效的工作负…

【论文阅读】ICCV 2023 计算和数据高效后门攻击

文章目录 一.论文信息二.论文内容1.摘要2.引言3.主要图表4.结论 一.论文信息 论文题目&#xff1a; Computation and Data Efficient Backdoor Attacks&#xff08;计算和数据高效后门攻击&#xff09; 论文来源&#xff1a; 2023-ICCV&#xff08;CCF-A&#xff09; 论文团…

AI文生图网站测评

主要测评文章配图生成效果、绘制logo等效果 测评关键点&#xff1a;生成效果、网站易用度、是否免费 测评prompt&#xff1a;请生成一个文章内容配图&#xff0c;图片比例是3&#xff1a;2&#xff0c;文章主旨是AI既是机遇&#xff0c;也存在挑战和风险&#xff0c;要求图片…

Matlab/simulink基于vsg的风光储调频系统建模仿真(持续更新)

​ 1.Matlab/simulink基于vsg的风光储调频系统建模仿真&#xff08;持续更新&#xff09;

leet hot 100-3 最长连续序列

两数之和 原题链接思路代码 原题链接 leet hot 100-3 128. 最长连续序列 思路 可以把所有的数字放到容器里面去 维护一个最大值 每一次去遍历数字 查看但当前数字是否为起始位置&#xff08;它的前面是否有比它小一位的数字&#xff09; 如果是起始位置 就记录一下当前值 并…

应用回归分析:泊松回归

泊松回归是一种广泛用于计数数据的回归分析方法。它适用于响应变量是非负整数的情况&#xff0c;特别是当这些计数呈现出明显的离散分布时。泊松回归通过泊松分布的概率分布函数来建模计数数据&#xff0c;使其成为处理计数数据的自然选择。本文将介绍泊松回归的基本概念、应用…

FastJson反序列化漏洞(Fastjson1.2.47)

一、FastJson Fastjson 是一个阿里巴巴公司开源的 Java 语言编写的高性能功能完善的 JSON 库。可以将Java 对象转换为 JSON 格式(序列化)&#xff0c;当然它也可以将 JSON 字符串转换为 Java 对象&#xff08;反序列化&#xff09; 它采用一种“假定有序快速匹配”的算法&…

【RAG实践】基于LlamaIndex和Qwen1.5搭建基于本地知识库的问答机器人

什么是RAG LLM会产生误导性的 “幻觉”&#xff0c;依赖的信息可能过时&#xff0c;处理特定知识时效率不高&#xff0c;缺乏专业领域的深度洞察&#xff0c;同时在推理能力上也有所欠缺。 正是在这样的背景下&#xff0c;检索增强生成技术&#xff08;Retrieval-Augmented G…

SpringBoot -【BeanPostProcessor】基础使用及应用场景

BeanPostProcessor应用与优化 1. 引言 在现代软件开发中&#xff0c;企业开发面临着越来越复杂的系统架构和业务需求。随着项目规模的扩大和技术栈的增多&#xff0c;需要更高效的工具来应对这些挑战&#xff0c;并确保代码的可维护性和扩展性。 在这样的背景下&#xff0c;Be…

第五章虚拟机栈

第五章虚拟机栈 文章目录 第五章虚拟机栈1. 虚拟机栈概述1.1 虚拟机栈出现的背景1.2 初步印象1.2.1 内存中的栈与堆 1.3 虚拟机栈基本内容1.3.1 Java虚拟机栈是什么&#xff1f;1.3.2 栈的特点(优点)1.3.3 栈中可能出现的异常1.3.4 设置栈内存大小 2. 栈的存储结构2.1 栈中存储…

安科瑞企业微电网智慧能源管理系统生态交流会顺利举行

2024年1月12日&#xff0c;安科瑞企业微电网智慧能源管理系统生态交流会顺利举行&#xff0c;本次会议旨在围绕双碳目标&#xff0c;共同探讨如何抓住新机遇、新市场&#xff0c;充分利用安科瑞企业微电网智慧能源的一站式服务&#xff0c;为企业节能、减碳、降本赋能&#xff…

第十一天-Excel的操作

目录 1.xlrd-Excel的读模块 安装 使用 获取工作簿 读取工作簿的内容 xlsxwriter-Excel的写模块 安装 使用 生成图表 add_series参数 图表的样式 demo&#xff1a;生成图表 Excel的操作在python中有多个模块&#xff0c;为了能够快速使用&#xff0c;选择了相对简单…

变分自编码器 VAE 超详解,从简单公式推导到模型结构到模型理解

参考文献&#xff1a; [1] Kingma D P, Welling M. Auto-encoding variational bayes[J]. arXiv preprint arXiv:1312.6114, 2013. [2] Doersch C. Tutorial on variational autoencoders[J]. arXiv preprint arXiv:1606.05908, 2016. [3] 变分自编码器&#xff08;一&#xff…

Linux学习方法-框架学习法——Linux应用程序编程框架

配套视频学习链接&#xff1a;https://www.bilibili.com/video/BV1HE411w7by?p4&vd_sourced488bc722b90657aaa06a1e8647eddfc 目录 Linux应用程序编程 Linux应用程序编程 Linux文件I/O(input/output) Linux文件I/O(五种I/O模型) Linux多进程 Linux多线程 网络通信(s…

ChatGPT在综合数据处理中的应用(续篇)

ChatGPT在综合数据处理中的应用&#xff08;续篇&#xff09; 小蜜蜂AI网站可以体验&#xff0c;扫码注册。 1.1 案例1: 用户连续活跃天数获取 ​ 用户连续活跃天天数有点类似于留存率指标&#xff0c;也能反映用户留存情况&#xff0c;实现逻辑稍微有些难度&#xff0c;我们…

第六章 本地方法接口

第六章 本地方法接口 文章目录 第六章 本地方法接口0. 前情提要1. 什么是本地方法2. 为什么要使用Native Method 0. 前情提要 图1 JVM架构 前几章讲完了类加载器子系统、运行时数据区的虚拟机栈和PC寄存器。这一节先穿插一节本地方法接口和本地方法库&#xff0c;再介绍本地方法…

第3.3章:StarRocks数据导入——Stream Load

一、概述 Stream Load是StarRocks最为核心的导入方式&#xff0c;用户通过发送HTTP请求将本地文件或数据流导入至StarRocks中&#xff0c;其本身不依赖其他组件。 Stream Load支持csv和json两种数据文件格式&#xff0c;适用于数据文件数量较少且单个文件的大小不超过10GB 的场…