JVM源码剖析之JIT工作流程

版本信息:

jdk版本:jdk8u40

思想至上

Hotspot中执行引擎分为解释器、JIT及时编译器,上篇文章描述到解释器过度到JIT的条件。JVM源码剖析之达到什么条件进行JIT优化 这篇文章大致讲述JIT的编译过程。在JDK中javac和JIT两部分跟编译原理挂钩,而编译原理抛开内部实现的算法,从思想的角度出发可以分为前端、中间IR、后端,见图1.1描述。比如拿javac举例,开发人员编写好xxx.java 文件,通过javac命令把xxx.java 文件编译成 xxx.class二进制文件交给JVM执行,其中编译的流程就如图1.1的流程。
图1.1 编译原理思想图
图1.1 编译原理思想图

而本文论述JIT,所以我们需要把编译原理的思想带入到JIT中,见图1.2,这里的输入为达到JIT编译阈值的方法对应的字节码,经过前端、中间IR语言、后端(这里为了容易理解,把前端、中间IR语言、后端想象成一个编译的黑盒程序)后得到输出结果为ISA指令集(ISA:CPU平台可执行指令)
图1.2 JIT的编译思想图
图1.2 JIT的编译思想图

源码论证

流程图先放在最前面,如图1.3
图1.3 JIT工作流程
图1.3 JIT工作流程

由图1.3可以得知Java工作线程(Java项目中运行的线程)和编译线程之间通过队列来通信(当然,这也是线程通信的最基本方式),CompileTask作为通信的载体,当Java线程执行某个方法当方法达到JIT优化的阈值或者回边计数器达到了阈值,此时会创建CompileTask投递到CompileQueue队列中。

/*
method_invocation_event
	->compile
		->submit_compile
			->compile_method
				->compile_method_base
					->create_compile_task
*/
// src/share/vm/compiler/compileBroker.cpp 文件中
CompileTask* CompileBroker::create_compile_task(CompileQueue* queue,
                                              int           compile_id,
                                              methodHandle  method,
                                              int           osr_bci,
                                              int           comp_level,
                                              methodHandle  hot_method,
                                              int           hot_count,
                                              const char*   comment,
                                              bool          blocking) {
  CompileTask* new_task = allocate_task();
  new_task->initialize(compile_id, method, osr_bci, comp_level,
                       hot_method, hot_count, comment,
                       blocking);
  // 给CompilerThread线程对应的队列投递编译任务。
  queue->add(new_task);
  return new_task;
}

java工作线程给编译线程队列投递任务后,此时编译线程开始干活,接收队列的compileTask任务,开始执行编译工作

// src/share/vm/compiler/compileBroker.cpp 文件中
void CompileBroker::compiler_thread_loop() {
  CompilerThread* thread = CompilerThread::current();
  // 拿到当前编译线程对应的队列
  CompileQueue* queue = thread->queue();

  …………

  while (!is_compilation_disabled_forever()) {
    // 从队列中获取到任务
    CompileTask* task = queue->get();
    if (task == NULL) {
      continue;
    }

    …………

    // 执行任务
    invoke_compiler_on_method(task);
  }
}

接下来的编译工作需要区分c1还是c2编译器,这个在Java工作线程投递compileTask任务的时候就已经确定(因为在检查阈值的时候即可确定)。在Hotspot中c1编译器用Compiler类作为抽象,c2编译器使用C2Compiler类作为抽象,不管是c1和c2都继承与AbstractCompiler,AbstractCompiler类中给予编译器公共的抽象。为了篇幅的简单,我们采用c1,也叫做client编译器。

/*
invoke_compiler_on_method
	->Compiler::compile_method(Compiler为c1编译器)
		->Compilation::Compilation
			->Compilation::compile_method
*/
// src/share/vm/c1/c1_Compilation.cpp 文件中
void Compilation::compile_method() {
  
  …………

  // compile method
  int frame_size = compile_java_method();

  if (InstallMethods) {		// 在c1编译器中,默认为true,也即编译完成后安装机器码。
    // 安装代码(实际上就是把机器码执行地址放入Method对象中,下次执行方法就会执行JIT编译好的代码)
    install_code(frame_size);
  }
  
  …………
}

int Compilation::compile_java_method() {

  // 从方法字节码构建出HIR中间语言。
  {
    PhaseTraceTime timeit(_t_buildIR);
    build_hir();
  }

  // 从HIR中间语言构建出LIR中间语言
  {
    PhaseTraceTime timeit(_t_emit_lir);
    _frame_map = new FrameMap(method(), hir()->number_of_locks(), MAX2(4, hir()->max_stack()));
    emit_lir();
  }

  // 从LIR中间语言生成机器代码
  {
    PhaseTraceTime timeit(_t_codeemit);
    return emit_code_body();
  }
}

在这里插入图片描述

整个c1编译器的编译过程就论述完毕了(仅仅是宏观上,微观上还存在众多算法和平台指令的生成,这个跟编译原理的算法和Hotspot中JIT优化的思想有关,这里不做论述)

这里对IR中间语言做一个简单的论述,为什么Hotspot中JIT需要存在HIR和LIR 2个中间语言呢?在编译原理中,IR的作用是承上启下,由于中间层的出现,这也让前端和后端更加灵活多变,此时,这也让笔者不经想起一句话" 计算机的世界没有加一个中间层解决不了的问题,如果不行,那就再加一层 ",并且有了中间层的出现,便可以在中间表示层做你想做的语言优化工作。说回Hotspot中,既然分了HIR(High-level Intermediate Representation)和LIR(Low-level Intermediate Representation)两层中间层,所以抽象的行为更加的具体,并且模块化更细粒度。HIR在JIT中是平台无关的中间语言,这一层完全可以用来对接字节码,并且做优化工作,优化完毕后,生成LIR中间语言,而LIR中间语言与平台相关,可以说已经非常接近平台相关指令(机器语言),这一层便可以做平台相关的优化工作。一层一层的过度,这像不像解释器过度到JIT的过程。

在GCC编译器中IR中间层就分为GENERIC、GIMPLE、RTL,也是一层一层的过度,最终RTL最接近机器语言的表现形式

在Coins编译器中,IR中间层也是分为HIR、LIR,跟Hotspot一样,从HIR过度到LIR,LIR接近机器语言的表现形式。

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

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

相关文章

游游的排列构造

示例1 输入 5 2 输出 3 1 5 2 4 示例2 输入 5 3 输出 2 1 4 3 5 #include<bits/stdc.h> using namespace std; typedef long long ll; const int N1e55; int n,k; int main(){scanf("%d%d",&n,&k);int xn-k1;int yn-k;int f1;for(int i1;i&l…

【前端】javascript+html+css 家具销售网站(代码+报告)

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

工业RFID读写器在食品饮料加工生产的应用!

当前食品饮料加工行业快速发展&#xff0c;得益于科技的应用&#xff0c;科技不仅提高了生产效率&#xff0c;还提升了食品生产质量和食品安全水平。其中&#xff0c;RFID技术在食品饮料行业中的应用对于加工生产帮助很大&#xff0c;RFID技术未来在食品饮料行业仍有巨大的潜力…

Mac 定时重启 TouchBar 脚本(缓解闪烁问题)

背景 Mac 笔记本 TouchBar 是真的脆啊&#xff0c;合盖使用一段时间就废了&#xff0c;右侧一直闪烁简直亮瞎眼 &#x1f602; 经过观察&#xff0c;总结出闪烁规律如下&#xff1a; 工作状态&#xff1a;不断操作电脑时&#xff0c;触控栏处于工作状态&#xff0c;几乎不闪…

明晚直播:可重构计算芯片的AI创新应用分享!

大模型技术的不断升级及应用落地&#xff0c;正在推动人工智能技术发展进入新的阶段&#xff0c;而智能化快速增长和发展的市场对芯片提出了更高的要求&#xff1a;高算力、高性能、灵活性、安全性。可重构计算区别于传统CPU、GPU&#xff0c;以指令驱动的串行执行方式&#xf…

5.开发DAO组件 -- Spring Data JPA

开发DAO组件 作用&#xff1a;用来访问数据库 持久化技术&#xff1a;Spring Data, JPA, Mybaits&#xff0c;jOOQ 等 Spring Boot为常见持久化技术提供了支持。 现在使用 Spring Data JPA Spring Data JPA 使用Spring Data JPA来访问数据库&#xff0c;需要再项目添加两个…

Python工具箱系列(三十九)

使用zlib对数据进行压缩 现实世界中&#xff0c;大量存在着对数据压缩的需求。为此&#xff0c;python内置了zlib压缩库&#xff0c;可以方便的对任意对象进行压缩。 下述代码演示了对字符串进行压缩&#xff1a; import zlib# 压缩一段中文 originstr 神龟虽寿&#xff0c…

Mysql触发器

1.触发器 触发器是与表有关的数据库对象&#xff0c;指在 insert / update / delete 之前或之后&#xff0c;触发并执行触发器中定义的SL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性&#xff0c;日志记录&#xff0c;数据校验等操作。 使用别名 OLD 和 …

python将多张图片拼成一张矩阵图,合成一张大图

用Python实现将多张图片排列成n*m的图像矩阵图 目录 引言环境准备代码实现效果演示总结 引言 在图像处理和图像展示的应用中&#xff0c;将多张图片排列成一个图像矩阵图是一个常见的需求。本博客介绍如何使用Python实现将12张图片排列成n*m的图像矩阵图。 环境准备 为了实…

【C# 6.0】云LIS平台源码

基于云计算的区域LIS平台为医疗机构改善患者服务质量提供了强有力的支持&#xff0c;“以患者为核心”这一理念得到了充分实现&#xff0c;可以解决各医院LIS建设水平参差不齐的现状&#xff0c;并完善各医院内LIS系统的功能&#xff0c;实现数据标准统一、功能完善、性能可靠&…

F5 LTM 知识点和实验 2-负载均衡基础概念

第二章&#xff1a;负载均衡基础概念 目标&#xff1a; 使用网页和TMSH配置virtual servers&#xff0c;pools&#xff0c;monitors&#xff0c;profiles和persistence等。查看统计信息 基础概念&#xff1a; Node一个IP地址。是创建pool池的基础。可以手工创建也可以自动创…

【计算机网络】应用层协议 -- 安全的HTTPS协议

文章目录 1. 认识HTTPS2. 使用HTTPS加密的必要性3. 常见的加密方式3.1 对称加密3.2 非对称加密3.3 非对称加密对称加密 4. 引入CA证书4.1 CA认证4.2 数据签名4.3 非对称机密对称加密证书认证4.4 常见问题 5. 总结 1. 认识HTTPS HTTPS全称为 Hyper Text Tranfer Protocol over …

页面访问控制远程仓库

页面访问权限控制 什么是jwt身份认证 在前后端分离模式的开发中&#xff0c;服务器如何知道来访者的身份呢&#xff1f; 在登录后&#xff0c;服务器会响应给用户一个 令牌 &#xff08;token&#xff09;令牌中会包括该用户的id等唯一标识浏览器收到令牌后&#xff0c;自己…

【极大似然性】不同函数(均方误差、交叉熵、KL 散度)不同结局(1/2)

Kowshik chilamkurthy 一、说明 很多时候&#xff0c;数据科学家和机器学习从业者并不欣赏不同损失指标之间的数学和直观关系&#xff0c;如负对数似然、交叉熵、最大似然估计、Kullback-Leibler &#xff08;KL&#xff09; 散度&#xff0c;以及最重要的均方误差。如果我说KL…

Windows11+Opencv+Clion编译源码

Windows11OpencvClion编译源码 参考&#xff1a;https://www.robotsfan.com/posts/69395e08.html 注意事项 编译过程中使用的软件&#xff0c;开源码等所有工具的安装路径一定不要有中文和空格。cmake过程会下载一些文件&#xff0c;如果是局域网的话可能下载不下来&#xf…

哈工大计算机网络课程网络安全基本原理详解之:消息完整性与数字签名

哈工大计算机网络课程网络安全基本原理详解之&#xff1a;消息完整性与数字签名 这一小节&#xff0c;我们继续介绍网络完全中的另一个重要内容&#xff0c;就是消息完整性&#xff0c;也为后面的数字签名打下基础。 报文完整性 首先来看一下什么是报文完整性。 报文完整性…

C++ ------ 模板初阶

文章目录 泛型编程模板函数模板概念原理函数模板的实例化类模板 泛型编程 我们在实现交换函数的时候&#xff0c;只能实现一个数据类型的交换函数&#xff0c;想要在C中完成对应类型数据的交换一种方法是使用函数重载&#xff0c;就像下面这样 void Swap(int& left, int&am…

开发一个RISC-V上的操作系统(五)—— 协作式多任务

目录 往期文章传送门 一、什么是多任务 二、代码实现 三、测试 往期文章传送门 开发一个RISC-V上的操作系统&#xff08;一&#xff09;—— 环境搭建_riscv开发环境_Patarw_Li的博客-CSDN博客 开发一个RISC-V上的操作系统&#xff08;二&#xff09;—— 系统引导程序&a…

【C++】类和对象(下)

1、初始化列表 初始化列表&#xff1a;以一个冒号开始&#xff0c;接着是一个以逗号分隔的数据成员列表&#xff0c;每个"成员变量"后面跟一个放在括号中的初始值或表达式。 class Date { public:Date(int year, int month, int day): _year(year), _month(month), _…

OpenLayers实战进阶专栏目录,OpenLayers实战案例,OpenLayers6实战教程

前言 本篇作为OpenLayers实战进阶教程的目录&#xff0c;用于整理汇总专栏所有文章&#xff0c;方便查找。 OpenLayers是前端最流行的JS二维地图引擎之一。 反馈建议 OpenLayers系列-交流专区&#xff0c;建议和问题反馈 Openlayers实战进阶 Openlayers实战&#xff0c;O…