当前位置: 首页 > news >正文

【JVM】深入JIT优化机制

1.JIT优化技术

在将高级语言转化为计算机可识别的机器语言时,常用的两种方式是编译和解释。Java在编译过程中,首先将代码编译成字节码。但是,字节码并不能直接在机器上执行。因此,JVM中内置了解释器(Interpreter),它在运行时将字节码逐行翻译成机器码并执行。

然而,解释器的执行方式是一边翻译,一边执行,导致执行效率较低。为了提高效率,HotSpot JVM引入了JIT(Just-In-Time)编译技术。

有了JIT技术后,JVM仍然通过解释器进行初始执行。但当JVM发现某个方法或代码块被频繁执行时,它将其标记为“热点代码”(Hot Spot Code)。JIT随后将这些热点代码编译为机器码,并进行优化。优化后的机器码被缓存起来,以便下次直接使用,从而显著提升执行效率。

2.热点检测

上面我们说过,要想触发JIT,首先需要识别出热点代码。目前主要的热点代码识别方式是热点探测,有以下两种

  1. 基于采样的方式探测: 周期性检测各个线程的栈顶,发现某个方法经常出现在栈顶,就认为是热点方法。好处就是简单,缺点就是无法精确确认一个方法的热度。容易受线程阻塞或别的原因千扰热点探测。

  2. 基于计数器的热点探测: 采用这种方法的虚拟机会为每个方法,甚至是代码块建立计数器,统计方法的执行次数,某个方法超过阀值就认为是热点方法,触发JIT编译。

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

    方法计数器。顾名思义,就是记录一个方法被调用次数的计数器

    回边计数器。是记录方法中的for或者while的运行次数的计数器

3.编译优化

逃逸分析

  1. 全局逃逸:对象超出了方法或线程的范围,比如被存储在静态字段作为方法的返回值
public class GlobalEscapeExample {private static object staticObject;public void globalEscape() {static object = new 0bject();// 这个对象赋值给静态字段,因此它是全局逃逸的}public static stringBuffer craetestringBuffer(string sl,string s2){StringBuffer sb =new stringBuffer();sb.append(s1);sb.append(s2);return sb;}
}

如我们新建的staticObject就是全局逃逸的。以及下面的方法中的sb对象,也是全局逃逸的。

  1. 参数逃逸: 对象被作为参数传递或被参数引用,但在方法调用期间不会全局逃逸。
public class ArgEscapeExample {public void methodA() {obiect localobject =new object();methodB(localobject);//localobject作为参数传递,但不会从methodB中逃逸}public void methodB(object param){//在这里使用param}
}

如传递到methodB中的param对象,就是发生了参数逃逸的。因为他从methodA中逃逸到了methodB中

  1. 无逃逸: 对象可以被标量替换,意味着它的内存分配可以从生成的代码中移除。
public static string createstringBuffer(string s1,string s2) {stringBuffer sb = new stringBuffer();sb.append(s1);sb.append(s2);return sb.tostring();
}

如上面的sb,就没有发生逃逸,因为这个对象本身没有作为参数传递,也没有被当做方法返回值,并没有赋值给静态变量。

在Java中,不同的逃逸状态影响JIT (即时编译器)的优化策略:

  1. 全局逃逸: 由于对象可能被多个线程访问,全局逃逸的对象一般不适合进行栈上分配或其他内存优化。但JIT可能会进行其他类型的优化,如方法内联循环优化

  2. 参数逃逸: 这种情况下,对象虽然作为参数传递,但不会被方法外部的代码使用。JIT可以对这些对象进行一些优化,例如锁消除

  3. 无逃逸: 这是最适合优化的情况。JIT可以采取多种优化措施,如在栈上分配内存,消除锁甚至完全消除对象分配 (标量替换)。这些优化可以显著提高性能,减少垃圾收集的压力。

方法内联

方法内联是Java中的一个优化技术,即时编译器JIT用它来提高程序的运行效率。在Java中,方法内联意味着将一个方法的代码直接插入到调用它的地方,从而避免了方法调用的开销。这种优化对于小型且频繁调用的方法特别有用。

锁消除

锁消除是 JIT 编译器在编译期间通过分析代码的同步块,判断是否存在锁竞争的可能性。如果某个锁在多线程环境下不存在竞争,那么它就可以在生成的机器码中消除这些锁操作,以减少不必要的开销。

栈上分配

栈上分配的好处:

  1. 减少GC压力:对象分配在栈上,当方法执行完毕后,栈上的内存会自动释放,不需要垃圾回收(GC)来管理,从而减少了GC的压力。
  2. 提高性能:栈上的内存分配和释放非常高效,因为它只是对栈指针进行简单的移动操作,而堆上的内存管理相对复杂,需要垃圾回收器的参与。

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

不一定,在HotSpot虚拟机中,存在JIT优化的机制,JIT优化中可能会进行逃逸分析,当经过逃逸分析发现某个对象不会逃逸出当前方法(即它只在方法内部使用),那么这个对象就不会被分配到堆上,而是进行栈上分配

标量替换

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

在JIT阶段,如果经过逃逸分析,发现一个对象不会被外界访问的话,那么经过JIT优化,就会把这个对象拆解成若干个其中包含的若干个成员变量来代替。这个过程就是标量替换

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • AI安全新纪元:智能体驱动的网络安全新范式
  • 【JavaEE初阶】文件操作和IO
  • 【基础篇】数据结构
  • 无缝融入,即刻智能[一]:Dify-LLM大模型平台,零编码集成嵌入第三方系统,42K+星标见证专属智能方案
  • 【Hot100】LeetCode—283. 移动零
  • [Spring] Spring AOP
  • 修复本地终端(windows)连接服务器使用zsh出现乱跳的问题
  • 有道云docx转换markdown,导入hugo发布到github page,多平台发布适配
  • 【Unity】案例 —— 胡闹厨房联机案例(持续更新)
  • css写一个按钮流光动画效果
  • Kubernetes-ingress
  • linux主机间免密登录
  • HBuidlerX 运行到Android App基座时提示没有检测到设备,该如何处理。
  • 002 | 常见的金融量化指标计算
  • Python电商网络数据采集实践||批量数据采集的API接口
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • chrome扩展demo1-小时钟
  • const let
  • ES学习笔记(12)--Symbol
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • JavaScript创建对象的四种方式
  • JS学习笔记——闭包
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • React组件设计模式(一)
  • Sass Day-01
  • Spring Boot快速入门(一):Hello Spring Boot
  • spring boot下thymeleaf全局静态变量配置
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 包装类对象
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 多线程事务回滚
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 前端设计模式
  • 浅谈Golang中select的用法
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • # C++之functional库用法整理
  • # Kafka_深入探秘者(2):kafka 生产者
  • #Datawhale AI夏令营第4期#多模态大模型复盘
  • #Linux(make工具和makefile文件以及makefile语法)
  • (LNMP) How To Install Linux, nginx, MySQL, PHP
  • (二)JAVA使用POI操作excel
  • (二)PySpark3:SparkSQL编程
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (十)T检验-第一部分
  • (算法)前K大的和
  • (算法)区间调度问题
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (转)jQuery 基础
  • (转)Scala的“=”符号简介
  • (转)项目管理杂谈-我所期望的新人
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .NET Windows:删除文件夹后立即判断,有可能依然存在