【Java JMM】编译和优化

news2025/6/22 19:22:03

1 前端编译

在 Java 技术下, “编译期” 是一个比较含糊的表述, 因为它可能指的是

  1. 前端编译器 (“编译器的前端” 更准确一些) 把 *.java 文件转变成 *.class 文件的过程
  2. Java 虚拟机的即时编译器 (常称 JIT 编译器, Just In Time Compiler) 运行期把字节码转变成本地机器码的过程
  3. 使用静态的提前编译器 (常称 AOT 编译器, Ahead Of Time Compiler) 直接把程序编译成与目标机器指令集相关的二进制代码的过程

这三者的代表性编译器产品

  1. 前端编译器: JDK 的 Javac, Eclipse JDT 中的增量式编译器 (ECJ)
  2. 即时编译器: HotSpot 虚拟机的 C1, C2 编译器, Graal 编译器
  3. 提前编译器: JKD 的 Jaotc, GNU Compiler for the Java (GCJ), Excelsior JET

这 3 类过程中最符合普通程序员对 Java 程序编译认知的应该是第一类。下面讨论的基本都限制在第一种情况。

1.1 Javac 源码

在 JDK8 中, Javac 的源码主要存放在 $JAVA_HOME/lib/tools.jar, 拷贝一份到一个地方, 解压后, 依次进入 com/sun/tools/javac, 这里就是源
码的地方。当然最简单的方式就是打开一包编译器, 顺便建立一个 Java 项目, 搜索 com.sun.tools.javac.Main 就可以了。

从 Javac 代码的总体结构来看, 编译过程大致可以分为 1 个准备过程和 3 个处理过程, 它们分别如下所示

  1. 准备过程: 初始化插入式注解处理器
  2. 解析与填充符号表过程, 包括

2.1 词法, 语法分析。将源代码的字符流转变为标记集合, 构造出抽象语法树
2.2 填充符号表。产生符号地址和符号信息

  1. 插入式注解处理器的注解处理过程: 插入式注解处理器的执行阶段
  2. 分析与字节码生成过程, 包括

4.1 标注检查。对语法的静态信息进行检查
4.2 数据流及控制流分析。对程序动态运行过程进行检查
4.3 解语法糖。将简化代码编写的语法糖还原为原有的形式
4.4 字节码生成。将前面各个步骤所生成的信息转化成字节码

上述 3 个处理过程里, 执行插入式注解时又可能会产生新的符号, 如果有新的符号产生, 就必须转回到之前的解析, 填充符号表的过程中重新处理这些新符号。
大体的流程如下:
Alt 'Java 处理器处理过程'

代码的入口: com.sun.tools.javac.main.JavaCompiler, 后面整个详细的流程省略。

流程:

  1. 词法分析, 源代码的字符流转变为标记 (Token) 集合, 主要由 com.sun.tools.javac.parser.Scanner 实现

  2. 语法分析, 根据标记序列构造抽象语法树, 主要由 com.sun.tools.javac.parser.Parser, 产生的抽象树为 com.sun.tools.javac.tree.JCTree

  3. 填充符号表, 对符号表进行填充, 主要由 com.sun.tools.javac.parser.Enter

  4. 注解处理器, 通过注解处理器, 可以对抽象语法树中的元素进行读取, 修改, 添加, 在处理注解期间对语法树进行过修改, 编译器将回到解析及填充符号表
    的过程重新处理, 直到所有插入式注解处理器都没有再对语法树进行修改为止。插入式注解处理器的初始主要为 com.sun.tools.javac.main.JavaCompiler.initPorcessAnnotations,
    而执行过程则为 com.sun.tools.javac.main.JavaCompiler.processAnnotions

  5. 语义分析, 是对结构上正确的源程序进行上下文相关性质的检查, 大体可以分为 2 个流程 标注检查 (JavaCompiler.attribute) 和控制流分析 (JavaCompiler.flow)。
    标注检查中, 会对源代码中做一个 “常量折叠 (Constant Folding)” 的优化 (int a = 1 + 4; ==> int a = 5)

  6. 解语法糖, 把语法糖还原回原始的基础语法结构, 由 com.sun.tools.javac.comp.TransTypes 和 com.sun.tools.javac.comp.Lower 完成

  7. 字节码生成, 由 com.sun.tools.javac.jvm.Gen 完成, 把前面各个步骤生成的信息 (语法树, 符号表) 转为字节码, 还会进行少了代码的添加和转换,
    类似于 和 , 将字符串的 + , 替换为 StringBuffer 或者 StringBuilder 的 append 操作

  8. 最终由 com.sun.tools.javac.jvm.ClassWriter 输出字节码, 生成 Class 文件。

2 后端编译

编译器无论在何时, 在何种状态下把 Class 文件转换成与本地基础设施 (硬件指令集, 操作系统) 相关的二进制机器码, 它都可以视为整个编译过程的后端。

2.1 即时编译器

目前主流的两款商用 Java 虚拟机 (HotSpot, OpenJ9) 里, Java 程序最初都是通过解释器 (Interpreter) 进行解释执行的, 当虚拟机发现某个方法或
代码块的运行特别频繁, 就会把这些代码认定为 “热点代码 (Hot Spot Code)”, 为了提高热点代码的执行效率, 在运行时, 虚拟机将会把这些代码编译成本
地机器码, 并以各种手段尽可能地进行代码优化, 运行时完成这个任务的后端编译器被称为即时编译器。

现在主流的 Java 虚拟机内部都同时包含解释器和编译器, 2 者各有好处。
当程序需要迅速启动和执行的时候, 解释器可以首先发挥作用, 省去编译的时间, 立即运行。当程序启动后, 随着时间的推移, 编译器逐渐发挥作用, 把越来
越多的代码编译成本地代码, 这样可以减少解释器的中间损耗, 获得更高的执行效率。
当运行环境的内存资源限制较大时, 使用解释执行可以节约内存, 反之, 可以使用编译执行提高效率。
解释器可以作为编译器激进优化 (不能保证所有情况都正确, 但大多数时候都能提升运行速度的优化) 的后备"逃生门", 通过逆优化退回到解释状态执行。

HotSpot 虚拟机中内置了两个 (或三个) 即时编译器: 客户端编译器 (Client Compiler, 简称 C1), 服务端编译器 (Service Compiler, 简称 C2),
还有 JDK10 出现的长期目标是替代 C2 的 Graal 编译器。

热点代码

  • 被多次调用的方法
  • 被多次执行的循环体

对于这两种情况, 编译的目标对象都是整个方法体, 而不会是单独的循环体。

HotSpot 采用基于计数器的热点探测 (Counter Based Hot Spot Code Detection) 的方式确定方法是否为 “热点代码”。 虚拟机会为每个方法 (甚至是代码块)
建立计数器, 统计方法的执行次数, 如果执行次数超过一定的阈值就认为它是 “热点方法”。

为了实现热点计数, HotSpot 为每个方法准备了两类计数器: 方法调用计数器 (Invocation Counter) 和回边计数器 (Back Edge Counter, “回边” 的
意思就是指在循环边界往回跳转)。调用计数器 + 回边计数器之和超过了阈值 (客户端模式, 默认为 1500 次, 服务端模式: 10000 次), 就会向即时编译器
提交一个该方法的代码编译请求。

2.2 提前编译器

2 种作法:
一条分支是做与传统 C, C++ 编译器类似的, 在程序运行之前把程序代码编译成机器码的静态翻译工作;
另外一条分支是把原本即时编译器在运行时要做的编译工作提前做好并保存下来, 下次运行到这些代码 (譬如公共库代码在被同一台机器其他 Java 进程使用)
时直接把它加载进来使用

3 参考

《深入理解Java虚拟机》- 周志明

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

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

相关文章

基于Java+Swing大鱼吃小鱼(期末95分以上)

基于JavaSwing大鱼吃小鱼 一、系统介绍二、效果展示1.视频演示2.运行效果 三、其他系统实现四、获取源码 一、系统介绍 1.GWindow类:窗口的绘制,继承JFrame类,其主要设置的内容有: 窗口的相关信息:宽度、…

React学习计划-React16--React基础(二)组件与组件的3大核心属性state、props、ref和事件处理

1. 组件 函数式组件&#xff08;适用于【简单组件】的定义&#xff09; 示例&#xff1a; 执行了ReactDOM.render(<MyComponent/>, ...)之后执行了什么&#xff1f; React解析组件标签&#xff0c;找到了MyComponent组件发现组件是使用函数定义的&#xff0c;随后调用该…

嘉康利新品VIVIX软糖面世中国

中国区总经理登台演绎劲舞“科目三”&#xff0c;你敢想&#xff1f;嘉康利中国总经理冉永夫再一次用惊艳众人的创意打破了你的认知。 这一幕发生在12月10日在苏州国际博览中心举办的嘉康利新产品发布盛典上。盛典开场&#xff0c;冉永夫便领衔经销商和专业舞者&#xff0c;用一…

EfficientDet:Scalable and Efficient Object Detection中文版 (BiFPN)

EfficientDet: Scalable and Efficient Object Detection EfficientDet&#xff1a;可扩展和高效的目标检测 摘要 模型效率在计算机视觉中变得越来越重要。本文系统地研究了用于目标检测的神经网络架构设计选择&#xff0c;并提出了几个关键的优化方法来提高效率。首先&…

教你在Linux上安装Node并用Electron打包deb和rpm包

Windows下无法打linux版本的包&#xff0c;如果你要打linux系统的amd64架构需要找一台linux amd64的系统打包&#xff0c;也可以在amd64下打arm架构的包&#xff0c;但是不能运行&#xff0c;需要放到arm架构的系统里才能运行。 下载linux的node环境 Index of /nodejs-releas…

Leetcode 134 加油站

题意理解&#xff1a; 给定n个站点&#xff0c;两个数组gas表达每个站点可加的油量&#xff0c;cost表达到下一站点所需耗费的油量。 gas [1,2,3,4,5], cost [3,4,5,1,2] 要求从下表为i的站点开始&#xff0c;刚好能支撑汽车在每个站点转一圈后回到出发位置。 解题思路&#…

Deployment Controller详解(上)

上一篇在《Kubectl 部署无状态应用》中介绍了如何使用 Deployment 部署五个 hello world 实例时&#xff0c;我们并没有详细探讨 Deployment Controller 的各项功能。因此&#xff0c;本文将深入介绍 Deployment Controller 的作用以及它能够完成的任务。 本文来自官方文档梳理…

CAS机制

Java中提供了很多原子操作类来保证共享变量操作的原子性。这些原子操作的底层原理都是使用了CAS机制。在使用一门技术之前&#xff0c;了解这个技术的底层原理是非常重要的&#xff0c;所以本篇文章就先来讲讲什么是CAS机制&#xff0c;CAS机制存在的一些问题以及在Java中怎么使…

浅谈测试自动化selenium之POM模式

基于本人也是一个初学者&#xff0c;在运用POM模式的时候记录一下自己的学习笔记。 如果你是大神&#xff0c;那么可以略过&#xff0c;如果你是初学者&#xff0c;希望对你有帮助。 本文阐述了以下几个问题&#xff1a; 什么叫POM模式 为什么要用POM模式 POM模式的思想 POM模…

前端案例—antdDesign的Select多选框组件加上全选功能

前端案例—antdDesign的Select多选框组件加上全选功能。 实现效果如下&#xff1a; Select 组件里有这个属性&#xff0c;可以利用这个对下拉菜单进行自定义。 const handleChange (e, value) > {setSelectState(e.target.checked)let arr productOptions?productOption…

AI绘画中CLIP文本-图像预训练模型

介绍 OpenAI 在 2021 年提出了 CLIP&#xff08;Contrastive Language–Image Pretraining&#xff09;算法&#xff0c;这是一个先进的机器学习模型&#xff0c;旨在理解和解释图像和文本之间的关系。CLIP 的核心思想是通过大规模的图像和文本对进行训练&#xff0c;学习图像…

口碑好的国产主食冻干猫粮品牌有哪些?盘点十大放心猫粮国产名单

冻干猫粮可以帮助猫咪摄入更多的水分&#xff0c;因为冻干是高蛋白质的食物&#xff0c;当猫咪吃了冻干猫粮后&#xff0c;会感到口渴&#xff0c;从而更主动地去喝水。对于那些不喜欢喝水的猫咪&#xff0c;可以将冻干复水后再喂给它们&#xff0c;这样也可以增加猫咪的水分摄…

Keil5软件仿真 定时器互补通道 波形输出(Logic Analyzer)

步骤一&#xff1a;管脚配置确认。 ①配置定时器的管脚模式为复用推挽输出模式&#xff08;GPIO_MODE_AF_PP&#xff09;&#xff01;&#xff01;&#xff01;&#xff0c;注意&#xff1a;复用开漏模式软件仿真时无波形。 步骤二&#xff1a;编译程序。 ①点击编译按钮。 …

【泛型中K T V E? Object等分别代表什么含 义】

✅ 泛型中K T V E? Object等分别代表什么含义 ✅ 典型解析✅代码示例 ✅ 典型解析 E - Element (在集合中使用&#xff0c;因为集合中存放的是元素) T-Type (Java 类) K- Key (键) V - Value (值) N - Number (数值类型) ? - 表示不确定的iava类型 (无限制通配符类型) …

机器学习:手撕 AlphaGo(一)

图 1-1: AphaGo 结构概览 1. 前言 AlphaGo 是一个非常经典的模型&#xff0c;不论从影响力还是模型设计上。它的技术迭代演进路径&#xff1a;AlphaGo&#xff0c;AlphaGoZero&#xff0c;AlphaZero&#xff0c;MuZero 更是十分精彩。相信有很多同学因为听了 AlphaGo 的故事对…

中国化妆品头部企业环亚集团携美肤宝、法兰琳卡、滋源、肌肤未来等“新朋友”加入实在智能数智生态圈

广州环亚化妆品科技股份有限公司&#xff08;以下简称“环亚集团”&#xff09;是一家综合性美容化妆品高新技术企业&#xff0c;旗下拥有美肤宝、法兰琳卡、滋源、肌肤未来等多个品牌&#xff0c;产品涵盖洁肤护肤、洗护发、身体护理、精油等多个领域。在中国、澳大利亚、美国…

upset 绘制

好久没有更新,今天来一个upset图的绘制 1.1 安装包 #绘制upset的包现在看来有三个 ## UpSet ### 最基本的upsetR包,使用方便,但是扩展不方便 devtools::install_github("hms-dbmi/UpSetR") ## complex-upset ### UpSet的升级款 支持ggplot2 devtools::install_git…

Multi-value PBS

参考文献&#xff1a; [CIM19] Carpov S, Izabachne M, Mollimard V. New techniques for multi-value input homomorphic evaluation and applications[C]//Topics in Cryptology–CT-RSA 2019: The Cryptographers’ Track at the RSA Conference 2019, San Francisco, CA, …

【C#】TimeSpan

文章目录 概述属性时间计算拓展来源 概述 TimeSpan结构&#xff1a;表示一个时间间隔。 它含有以下四个构造函数&#xff1a; TimeSpan(Int64)将 TimeSpan结构的新实例初始化为指定的刻度数。&#xff08;DateTime.Tick:是计算机的一个计时周期&#xff0c;单位是一百纳秒&…

饥荒Mod 开发(十七):手动保存和加载,无限重生

饥荒Mod 开发(十六)&#xff1a;五格装备栏 饥荒Mod 开发(十八)&#xff1a;Mod 添加配置选项 饥荒游戏会自动保存&#xff0c;本来是一个好的机制&#xff0c;但是当角色死亡的时候存档会被删除&#xff0c;又要从头开始&#xff0c;有可能一不小心玩了很久的档就直接给整没了…