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 methodint 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接近机器语言的表现形式。

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

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

相关文章

使用Kmeans算法完成聚类任务

聚类任务 聚类任务是一种无监督学习任务,其目的是将一组数据点划分成若干个类别或簇,使得同一个簇内的数据点之间的相似度尽可能高,而不同簇之间的相似度尽可能低。聚类算法可以帮助我们发现数据中的内在结构和模式,发现异常点和离…

72. ElasticSearch常用命令

索引管理 1新建索引 curl -XPUT http://10.42.172.35:9200/index012 读写权限 curl -XPUT -d {"blocks.read":false} http://10.42.172.35:9200/index01/_settings3 查看索引 单个 curl -XGET http://10.42.172.35:9200/index01/_settings多个 curl -XGET http…

KMP 串的模式匹配 分数 25

先记录一个小坑。 int KMP() {getNext();int i 0, j 0;//写成下面这样&#xff0c;结果不对。原因是&#xff0c;当j-1时&#xff0c;循环条件-1 < strlen(P)被认为是false&#xff0c;会跳出循环while (i < strlen(T) && j < strlen(P)) {if (j -1 || T[…

小研究 - 一种复杂微服务系统异常行为分析与定位算法(一)

针对极端学生化偏差&#xff08;&#xff25;&#xff58;&#xff54;&#xff52;&#xff45;&#xff4d;&#xff45; &#xff33;&#xff54;&#xff55;&#xff44;&#xff45;&#xff4e;&#xff54;&#xff49;&#xff5a;&#xff45;&#xff44; &#…

3、Winform表单控件

在学习了布局控件之后,我们就该学习表单控件了。表单控件可以设置默认值,使用属性窗口或使用代码都是可以的。属性窗口最终也很转化成代码。 程序的本质=输入+处理+输出。在Winform程序角度,这里的输入输出就可以用我们的表单控件来实现。 表单控件大致可分为两类,文本控…

Python爬取IP归属地信息及各个地区天气信息

一、实现样式 二、核心点 1、语言&#xff1a;Python、HTML&#xff0c;CSS 2、python web框架 Flask 3、三方库&#xff1a;requests、xpath 4、爬取网站&#xff1a;https://ip138.com/ 5、文档结构 三、代码 ipquery.py import requests from lxml import etree # 请求…

前端html中让两个或者多个div在一行显示,用style给div加上css样式

文章目录 前言一、怎么让多个div在一行显示 前言 DIV是层叠样式表中的定位技术&#xff0c;全称DIVision&#xff0c;即为划分。有时可以称其为图层。DIV在编程中又叫做整除&#xff0c;即只得商的整数。 DIV元素是用来为HTML&#xff08;标准通用标记语言下的一个应用&#x…

概念、框架简介--ruoyi学习(一)

开始进行ruoyi框架的学习&#xff0c;比起其他的前后端不分离的&#xff0c;这个起码看的清晰一些吧。 这一节主要是看了ruoyi的官方文档后&#xff0c;记录了以下不懂的概念&#xff0c;并且整理了ruoyi框架中的相关内容。 一些概念 前端 store store是状态管理库&#x…

数值线性代数: 共轭梯度法

本文总结线性方程组求解的相关算法&#xff0c;特别是共轭梯度法的原理及流程。 零、预修 0.1 LU分解 设&#xff0c;若对于&#xff0c;均有&#xff0c;则存在下三角矩阵和上三角矩阵&#xff0c;使得。 设&#xff0c;若对于&#xff0c;均有&#xff0c;则存在唯一的下三…

中科院放大招:FastSAM快速细分任何东西

FastSAM是一个用于图像分割的快速模型&#xff0c;它是对SAM&#xff08;Segment Anything Model&#xff09;模型的改进和优化。FastSAM模型的目标是提高计算效率&#xff0c;使得图像分割任务能够更快地完成。 FastSAM模型的优势主要体现在以下几个方面&#xff1a; 快速性…

2023年7月26日 单例模式

单例模式 饿汉模式 package com.wz.cinema.platform.server.util;public class DataManager {/*** 单例模式&#xff1a;整个类在运行中只会有一个实例* 既然是在运行中只有一个实例&#xff0c;那么就必须* 考虑多线程环境** 单例模式分为懒汉模式和饿汉模式* 饿汉模式本身就是…

opencv03-Mat矩阵API的使用

opencv03-Mat矩阵API的使用 构造方法(具体介绍看API文档) int main() {Mat m1 Mat(200, 100, CV_8UC1);imshow("o1", m1);Mat m2 Mat(Size(100, 200), CV_8UC1);imshow("o2", m2);Mat m3 Mat(200, 100, CV_8UC3, Scalar(255, 0, 0));imshow("o3&…

【Linux进程篇】进程概念(1)

【Linux进程篇】进程概念&#xff08;1&#xff09; 目录 【Linux进程篇】进程概念&#xff08;1&#xff09;进程基本概念描述进程-PCBtask_struct-PCB的一种task_ struct内容分类 组织进程查看进程通过系统调用获取进程标示符通过系统调用创建进程——fork初识 作者&#xff…

Qt几种字符类型的相互转换

Qt几种字符类型的相互转换 将const QString转换为const char*将const char*转换为const QStringQstring转换为string把string转换为QstringQt中弹出一个窗口 将const QString转换为const char* #include <QString> #include <iostream>int main() {const QString …

【Docker】Docker应用部署之Docker容器安装Redis

目录 一、搜索Redis镜像 二、拉取Redis镜像 三、创建容器 四、测试使用 一、搜索Redis镜像 docker search redis 二、拉取Redis镜像 docker pull redis:版本号 # 拉取对应版本的redis镜像 eg: docker pull redis:5.0 三、创建容器 docker run -id --nameredis -p 6379:637…

Games101学习笔记 - 变换矩阵基础

二维空间下的变换 缩放矩阵 缩放变换: 假如一个点&#xff08;X,Y&#xff09;。x经过n倍缩放&#xff0c;y经过m倍缩放&#xff0c;得到的新点&#xff08;X1&#xff0c;Y1&#xff09;&#xff1b;那么新点和远点有如下关系&#xff0c;X1 n*X, Y1 m*Y写成矩阵就是如下…

ChatGPT与高等教育变革:价值、影响及未来发展

最近一段时间&#xff0c;ChatGPT吸引了社会各界的目光&#xff0c;它可以撰写会议通知、新闻稿、新年贺信&#xff0c;还可以作诗、写文章&#xff0c;甚至可以撰写学术论文。比尔盖茨、马斯克等知名人物纷纷为此发声&#xff0c;谷歌、百度等知名企业纷纷宣布要提供类似产品。…

玩转Tomcat:从安装到部署

文章目录 一、什么是 Tomcat二、Tomcat 的安装与使用2.1 下载安装2.2 目录结构2.3 启动 Tomcat 三、部署程序到 Tomcat3.1 Windows环境3.2 Linux环境 一、什么是 Tomcat 一看到 Tomcat&#xff0c;我们一般会想到什么&#xff1f;没错&#xff0c;就是他&#xff0c;童年的回忆…

安全基础 --- html标签 + 编码

html标签 &#xff08;1&#xff09;detail标签 <details>标签用来折叠内容&#xff0c;浏览器会折叠显示该标签的内容。 <1> 含义&#xff1a; <details> 这是一段解释文本。 </details> 用户点击这段文本&#xff0c;折叠的文本就会展开&#x…

MySQL_2.6【高级查询2】详细讲解

目录 一、多表查询 1、笛卡尔积现象 2、等值连接查询 3、自连接查询 4、内连接查询 5、外连接 二、子查询 1、单列子查询 2、单行子查询 3、多行子查询 4、多列子查询 5、关联子查询【了解】 6、子查询的综合应用 加油&#xff01;&#xff01;&#xff01; 一、多…