JIT(即时编译)技术

介绍一下JIT优化技术?

想要把高级语言转变成计算机认识的机器语言有两种方式,分别是编译和解释,虽然Java转成机器语言的过程中有一个步骤是要编译成字节码,但是,这里的字节码并不能在机器上直接执行。

JVM中内置了 解释器(interpreter),在运行时对字节码进行解释翻译成机器码,然后再执行。

解释器 的执行方式是 一边翻译、一边执行,因此执行效率较低。为了解决这个低效率问题,HotSppot 引入了JIT 技术(Just-In-Time,即时编译)。此时:

  • JVM仍然是通过解释器进行解释执行;
  • 但是当JVM发现某个方法或代码块运行时执行的很频繁,就会认为是“热点代码(Hot Spot Code)”。然后JIT 会把部分 热点代码 翻译为 机器码 并进行优化,同时会把翻译后的机器码缓存起来,以备下次使用。

在这里插入图片描述

介绍一下 JIT 的两种编译器?

HotSppot 虚拟机中内置了两个 JIT编译器:Client CompilerServer Compiler

  • 客户端编译器(Client Compiler):也被称为 C1 编译器。C1 编译器会对代码进行简单的优化,并专注于提高编译速度。
  • 服务端编译器(Server Compiler):也被称为 C2 编译器。它是为了长时间运行的服务器端应用程序而设计的,因此在启动时可能会比 C1 编译器慢。C2 编译器会进行更复杂的优化,如全局优化、内联等,以获得更高的运行效率。

HotSpot 虚拟机提供了哪三种运行模式?

HotSpot 虚拟机提供了三种运行模式,这些模式主要影响即时编译器(JIT)的行为与性能:

  1. 解释模式(Interpreted Mode):即所有代码都解释执行,而不经过 JIT 编译。使用 -Xint 参数可以打开这个模式。

    优点:启动快速,没有编译延迟;缺点:运行效率相对较低;

  2. 编译模式(Compiled Mode):Java 字节码会由 JIT 编译器编译成本地机器码后执行。这通常包括 C1 和 C2 编译器,它们分别负责客户端编译和服务端编译。

    优点:比解释模式 运行效率高;缺点:启动时间较长,因为需要时间来编译代码。

  3. 混合模式(Mixed Mode):HotSpot 虚拟机的默认模式。在混合模式下,Java 虚拟机会同时使用解释器和编译器。刚开始运行时,字节码由解释器执行,随着程序的运行,热点代码(即执行频率较高的代码)会被 JIT 编译器编译成本地机器码。

    优点:结合了解释模式的快速启动编译模式的高效运行

-Xint:强制虚拟机运行于解释模式。
-Xcomp:强制虚拟机运行于编译模式。
不指定或使用 -Xmixed:默认使用混合模式。

可以通过java -version命令查看运行模式:(下图是 混合模式)

在这里插入图片描述

什么是 热点检测?

JIT (即时编译) 中讲到【当JVM发现某个方法或代码块运行时执行的很频繁,就会认为是“热点代码(Hot Spot Code)”】。目前,主要识别 热点代码的方式是 热点检测(Hot Spot Detection)

  1. 基于采样的方式探测(Sample Based Hot Spot Detection):周期性检测各个线程的栈顶,发现某个方法经常出现在栈顶,就认为是热点方法。

    好处就是简单;缺点就是无法精确确认一个方法的热度。容易受线程阻塞或别的原因干扰热点探测。

  2. 基于计数器的热点探测(Counter Based Hot Spot Detection):虚拟机会为每个方法、代码块建立计数器,统计方法的执行次数,某个方法超过阀值就认为是热点方法,触发JIT编译。

在HotSpot虚拟机中使用的是第二种,基于计数器的热点探测。因此它为每个方法准备了两个计数器:

  • 方法调用计数器:记录方法被调用的次数;
  • 回边计数器:记录方法中的for或者while运行的次数;

编译优化

JIT除了之前提到的可以将 字节码 翻译为 机器码 缓存起来。还会对代码做各种优化,比如:逃逸分析、锁消除、锁膨胀、方法内联、空值检查消除、类型检测消除、公共子表达式消除

讲讲 逃逸分析?

答:逃逸分析 是 HotSpot虚拟机 的 server 编译器 中 JIT 优化的一个重要步骤。对象基于逃逸分析有三种状态:全局逃逸(Global Escape)、参数逃逸(Arg Escape)、无逃逸(No Escape)。不同的逃逸状态 会影响 JIT (即时编译) 的优化策略

  • 全局逃逸(Global Escape):对象超出了方法或线程的范围,比如被存储在 静态字段、或作为方法的返回值
  • 参数逃逸(Arg Escape):对象被作为 参数传递、或被参数引用,但在方法调用期间不会全局逃逸。
  • 无逃逸(No Escape):对象可以被 标量替换,意味着它的内存分配可以从生成的代码中移除。

补充:

  • 全局逃逸:新创建的staticobject就是全局逃逸。第二个函数中的 sb也全局逃逸,因为它作为方法的返回值了。

    public class GlobalEscapeExample {private static object staticobject;public void globalEscape() {staticobject = new object();  //这个对象赋值给静态字段,因此它是全局逃逸的}public static stringBuffer craetestringBuffer(String s1,string s2) {stringBuffer sb = new stringBuffer( );sb.append(s1);sb.append(s2);return sb;
    }
    
  • 参数逃逸:传递到methodB中的 param对象,发生了参数逃逸,因为他从methodA中逃逸到了methodB中。

    public class ArgEscapeExample {public void methodA() {object localobject = new object();methodB(localObject); // localObject作为参数传递,但不会从methodB中逃逸}public void methodB(object param) {//在这里使用param}
  • 无逃逸:sb没有发生逃逸,因为这个对象本身 并没有作为参数传递、也没有作为方法的返回值,也没有赋值给静态变量。

    public static stringBuffer craetestringBuffer(String s1,string s2) {stringBuffer sb = new stringBuffer( );sb.append(s1);sb.append(s2);return sb.toString();
    }
    

逃逸状态 对 JIT 优化策略 的影响?

在java中,不同的 逃逸状态 会影响 JIT 的优化策略:

  1. 全局逃逸:由于对象可能被多个线程访问,全局逃逸的对象一般不适合进行栈上分配 或 其他内存优化。但是JIT 可能会进行其他类型优化(如 方法内联 或者 循环优化);
  2. 参数逃逸:对象虽然作为参数传递,但不会被方法外部的代码使用。因此JIT可以对这些对象进行优化(如:锁消除);
  3. 无逃逸:这是最适合优化的情况。JIT可以采取多种优化措施,比如在 站上分配内存、消除锁、标量替换;(这些优化可以显著提高性能,减少垃圾收集的压力)

下图是三种情况可以、不可以进行的优化手段:

as

逃逸分析 技术并不成熟?

答:是的,关于逃逸分析相关的援救很早就有了(1999年),但知道 JDK1.6才使用。

根本原因是,无法保证逃逸分析 的性能消耗 高于 它所带来的收益。因为逃逸分析自身也需要经过一系列复杂的分析,也是比较耗时的过程。

介绍什么是 锁消除?

动态编译:是指 JIT(Just-In-Time)编译器在程序运行时对 Java 字节码进行的即时编译。

在动态编译同步块时,JIT编译器可以借助 逃逸分析 来判断同步块所使用的锁对象 是否只能够被一个线程访问,而没有被发布到其他线程。

如果同步块所使用的 锁对象 通过分析被证实只能被一个线程访问,那么JIT编译器在编译这个同步块的时候就会取消这部分代码的同步。这个取消同步的过程就叫做同步省略,即锁消除


例子:下面代码对hollis这个对象进行加锁,但是该对象的生命周期只在f()方法中,并不会被其他线程所访问。

public void f() {object hollis = new object( );synchronized(hollis) {system.out.println( hollis);}
}

所以,在JIT编译阶段会被优化掉,优化为:

public void f() {object hollis = new object( );system.out.println( hollis);
}

标量替换 & 栈上分配?

标量替换

  • **标量(Scalar)**是指一个无法再分解为更小数据的数据。比如Java中的原始数据类型就是标量。相对的,那些还可以分解的数据叫做聚合量(Aggregate) ,Java中的对象就是聚合量,因为他可以分解成其他聚合量和标量。

  • 标量替换:在JIT阶段,经过逃逸分析,发现一个对象不会被外界访问。那么JIT优化就会将这个对象拆解成若干标量来替代,这个过程就是标量替换。好处就是:不需要在堆内存上分配内存,节省堆内存空间


标量替换的例子:

在这里插入图片描述

示例中,point对象没有逃逸出alloc方法,并且point对象是可以被分解为标量的。所以在JIT优化时,point对象不会被创建,而是直接使用两个标量int x, int y来替代point对象。

栈上分配

一般情况下,对象、数组元素 在内存中会被分配到 堆内存 上。但是随着JIT编译器的日渐发展,JIT编译器在运行期间进行逃逸分析,来决定是否可以将对象的内存分配 从 堆 转化为 栈

hotspot的栈上分配其实就是通过前面我们说过的标量替换实现的!

Java中的对象一定在堆上分配内存吗?

答:不一定。在HotSpot虚拟机中,存在JIT优化的机制,JIT优化中可能会进行逃逸分析,当经过逃逸分析发现某一个局部对象没有逃逸到线程和方法外的话,那么这个对象就可能不会在堆上分配内存,而是进行栈上分配(也就是会 通过标量替换,将对象分解为 标量,在栈上分配)。

方法内联

方法内联是指:将一个方法的代码直接插入到调用它的地方,从而避免了方法调用的开销。这种优化对于小型且频繁调用的方法特别有用

即时编译器(JIT)用它(方法内联)来提高程序的运行效率。


示例:
在这里插入图片描述

上面例子中,被调用方法add()内部逻辑非常简单。因此在JIT优化期间,可能会将add方法直接内敛在 调用处,避免了对add方法的实际调用。从而减少调用开销。

JIT优化可能带来的问题

一句话总结的可能带来的问题:就是JIT在优化之前,都是由解释器执行的代码,此时如果请求量大则会出现请求超时的问题

JIT开始优化之前:JIT优化是在运行期进行的,并且也不是Java进程刚一启动就能优化的,是需要先执行一段时间的,因为他需要先知道哪些是热点代码。

  • 所以,在IT优化开始之前,我们的所有请求,都是要经过解释执行的,这个过程就会相对慢一些。

  • 而且,如果应用的请求量比较大的的话,这种问题就会更加明显,在应用启动过程中,会有大量的请求过来,这就会导致解释器持续的在努力工作。解释器一旦对CPU占用较高,就会导致应用的性能进一步下降。

    这也是为什么很多应用在发布过程中,会出现刚重启的应用会发生大量的超时。

同时,随着请求不断增多,JIT优化会被触发。优化之后,后续的热点请求的执行就不再通过解释器了,而是直接通过JIT优化后的缓存机器码。这样就会快很多。

如何解决 JIT优化可能带来的问题?

现在已经知道JIT优化可能带来的问题:JIT在优化之前,都是由解释器执行的代码,此时如果请求量大则会出现请求超时的问题。

解决该问题有两种思路:

  1. 提升JIT的优化效率:比如可以使用阿里研发的JDK – Dragonwell。这个相比OpenJDK提供了一些专有特性,其中一项叫做JwarmUp的技术就是解决JIT优化效率的问题的。

    这个技术主要是通过记录Java应用上一次运行时候的编译信息到文件中,在下次应用启动时,读取该文件,从而在流量进来之前,提前完成类的加载、初始化和方法编译,从而跳过解释阶段,直接执行编译好的机器码

  2. 降低瞬时请求量:除了针对JDK做优化之外,还可以采用另外一种方式来解决这个问题,那就是做预热。在程序刚启动时,通过调节负载均衡,不要很快的把大流量分给它,而是先给其一小部分流量,通过这部分流量出发JIT优化。等优化好之后,再把流量调大。

对JDK进程执行kill -9有什么影响?

答:kill -9实际上是向该进程发送了SIGKILL信号,该命令会立刻终止进程,而不会给进程任何机会进行清理工作或执行任何终止前的代码

因此会造成:

  1. 导致数据丢失或损坏:如果Java进程正在处理数据(如写入文件或数据库),kill -9可能会导致数据处理中断,从而造成数据丢失或损坏。
  2. 不会执行清理代码:Java程序中可能有一些清理资源的代码(如关闭文件、网络连接、释放锁等),这些代码通常会在JVM正常关闭时执行。使用kill -9会跳过这些清理步骤,可能导致资源泄漏或数据不一致。
  3. 不会执行 Shutdown Hook:在Java中,你可以通过Runtime.addShutdownHook添加Shutdown Hook,这些Hook通常用于执行一些需要在JVM关闭时执行的操作。kill -9不会触发这些Hook的执行。

kill -9 与 kill -15 的区别

注意:kill 命令默认的信号就是15。

kill -15:会发送一个SIGTERM的信号给对应的程序。当应用程序接收到该信号时,具体如何处理,应用程序可以自己决定。可选择的有:

  • 立即停止程序
  • 释放响应资源后停止程序
  • 忽略该信号,继续执行程序

也就是说,kill -15信号,只是通知对应的进行要进行“安全干净的退出”,程序进程接收到该信号之后,会先进性一些准备工作(如释放资源、临时文件清理),然后在进行程序的终止

所以,相比于kill -15命令,kill -9在执行时,应用程序是没有时间进行"准备工作”的,所以这通常会带来一些副作用,数据丢失或者终端无法恢复到正常状态等。

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

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

相关文章

记软件开发者画图(UML),使用WPS应用制图

目录 前言 一、什么是UML 二、使用什么画图工具 三、示例 ​四、IntelliJ IDEA 2021快速生成UML图 前言 做软件开发的从写第一个示例程序到最后写项目程序避不开的需要设计画图,所以今天我们就来梳理一下‌UML(统一建模语言)图形需要画…

LINUX网络编程:TCP(1)

目录 1.认识Tcp的报头 2.确认应答机制(ACK) 序号与确认序号 捎带应答 3.超时重传机制 4.Tcp连接管理 三次握手 为什是三次握手 四次挥手 理解TIMEWAIT 1.认识Tcp的报头 源端口和目的端口号没什么说的 32位的序号和确认序号,之后会介…

T9-猫狗识别2(暂时版qaq)

T9周:猫狗识别2 **一、前期工作**1.设置GPU,导入库2.导入数据3.查看数据 **二、数据预处理**1.加载数据2.可视化数据3.配置数据集 **三、构建CNN网络模型****四、编译模型****五、训练模型****六、模型评估****七、预测**八、总结(暂时) &…

倒排索引(反向索引)

倒排索引(Inverted Index)是搜索引擎和数据库管理系统中常用的一种数据结构,用于快速检索文档集合中的文档。在全文搜索场景中,倒排索引是一种非常高效的手段,因为它能够快速定位到包含特定关键词的所有文档。 1、基本…

【Python技术】使用akshare、pyecharts绘制K线图

下班回到家,回家途中瞄了下股票,大盘又是3000多只股票待涨, 盘中上证指数一度跌破2700。 估计不少人心里不爽,那就聊聊相关技术学习下。 之前写过【python技术】使用akshare、pandas、mplfinance绘制红绿色K线图简单示例 &#x…

Android Retrofit源码分析(一):Retrofit是什么?和OkHttp的区别是什么?为什么需要他?

目录 一、Retrofit是什么? Retrofit是一个基于OKHttp的RESTful网络请求框架,由Square公司开源,专为Android和Java提供类型安全的HTTP客户端。它可以理解为OKHttp的加强版,底层封装了OKHttp,主要负责网络请求接口的封装,使得网络请求工作更加简洁高效。 简单来说,Retro…

GNN-RAG:用于大模型推理的图神经检索

GNN-RAG:用于大模型推理的图神经检索 秒懂大纲提出背景解法拆解全流程优化创意总结 论文:GNN-RAG: Graph Neural Retrieval for Large Language Model Reasoning 代码:https://github.com/cmavro/GNN-RAG 秒懂大纲 ├── GNN-RAG【主题】…

医疗领域患者监控中的手势识别:一种深度卷积神经网络方法

这篇论文的标题是《Hand Gesture Recognition for Patient Monitoring in the Medical Field: A Deep Convolution Neural Networks Approach》,作者们来自印度的Chaitanya Bharathi Institute of Technology电子与通信工程系。论文主要探讨了在医疗领域&#xff0c…

AI大模型之旅--milvus向量库安装

milvus-向量索引库 milvus的官方文档中看到最新版本的部署方式 :https://milvus.io/docs/install_standalone-docker.md 部署 curl -sfL https://raw.githubusercontent.com/milvus-io/milvus/master/scripts/standalone_embed.sh -o standalone_embed.sh 如果下载不下来&a…

C语言中值传递

C语言中&#xff0c;值传递的问题 #include <stdio.h> void modifyValue(int x) { x 10; // 修改的是x的副本&#xff0c;对原始数据无影响 printf("在函数中修改的结果是:%d\n",x); }int main() { int a 5; printf("Before: %d\n", a); modifyV…

基于协同过滤+SpringBoot+Vue的剧本杀服务平台系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于协同过滤JavaSpringBootV…

zynq SDK 关于SD卡报错

在修改了BD的部分代码之后&#xff0c;重新综合工程生成bit&#xff0c;之后刷新hdf文件&#xff0c;在SDK端就出现了SD卡相关的函数未定义的报错&#xff1a; Description Resource Path Location Type E:\Work\VivadoPrj\Prj1\project_1\project_1.sdk\Test\Debug/…/src/hel…

29. 查看threejs自带几何体顶点

查看three.js自带几何体顶点结构&#xff0c;基类(父类)BufferGeometry three.js提供的矩形平面PlaneGeometry、长方体BoxGeometry、球体SphereGeometry等各种形状的几何体&#xff0c;他们都有一个共同的父类BufferGeometry。这意味着这些几何体有哪些属性或方法&#xff0c;…

Bigemap GIS Office 2024注册机 全能版地图下载软件

对于需要利用GIS信息进行编辑、设计的用户来说&#xff0c;Bigemap GIS Office占有重要地位。用户可以使用Bigemap GIS Office作为工具进行设计、分析、共享、管理和发布地理信息。Bigemap GIS Office能实现多种数据流转、嵌入、融合以及更多地为用户提供数据的增强处理及多种分…

如何根据协议请求去捕捉在个文件中发出去的

场景&#xff1a;随着业务越来越复杂&#xff0c;一个“触发”可能发出去N个协议&#xff0c;此时有某一个协议发生了报错&#xff0c;需要去找这个协议&#xff0c;去文件中走读逻辑&#xff0c;去找该协议&#xff0c;效率很慢&#xff0c;业务极其复杂的情况下&#xff0c;很…

力扣53-最大子序和(Java详细题解)

题目链接&#xff1a;力扣53-最大子序和 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 dp五部曲。 1.确定dp数组和i下标的含义。 2.确定递推公式。 3.dp初始化。 4.确定dp的遍历顺序。 5.如果没有ac打印dp数组 利于debug。 每一个…

【时时三省】(C语言基础)指针笔试题1

山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 笔试题1: 创建了一个a数组 它有五个元素 五个元素分别是1 2 3 4 5 &a取出来的是一维数组的地址 然后产生的结果强制类型转换了成int &a+1就是从1跳到了5 如下图 再把这个地…

基于SSM+Vue+MySQL的酒店管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着旅游业的蓬勃发展&#xff0c;酒店业作为旅游产业链中的重要一环&#xff0c;面临着日益增长的客户需求和激烈的市场竞争。传统的人工酒店管理模式已难以满足高效、精准、个性化的服务要求。因此&#xff0c;开发一套基于SS…

OpenCV特征检测(6)对初步检测到的角点位置进行亚像素级别的精炼函数cornerSubPix()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 细化角点的位置。 该函数迭代以找到角点或径向鞍点的亚像素级准确位置&#xff0c;如 93中所述&#xff0c;并如下图所示。 亚像素级准确的角点…

Unsupervised Deep Representation Learning for Real-Time Tracking

摘要 我们的无监督学习的动机是稳健的跟踪器应该在双向跟踪中有效。具体来说&#xff0c;跟踪器能够在连续帧中前向定位目标对象&#xff0c;并回溯到其在第一帧中的初始位置。基于这样的动机&#xff0c;在训练过程中&#xff0c;我们测量前向和后向轨迹之间的一致性&#xf…