Java面试题之关于JIT编译器的那些个优化项

简介: 目录一、关于解释器和编译器1、概述2、JIT(Just In Time)编译器二、JIT优化之锁粗化 & 锁消除三、JIT优化之逃逸分析 & 栈上分配 & 同步消除 & 标量替换1、概念描述2、逃逸分析代码示例3、逃逸分析失效示例四、JIT优化之方法内联(Inline Method)1、概述2、方法内联示例3、方法内联的优点

目录

一、关于解释器和编译器

1、概述

2、JIT(Just In Time)编译器

二、JIT优化之锁粗化 & 锁消除

三、JIT优化之逃逸分析 & 栈上分配 & 同步消除 & 标量替换

1、概念描述

2、逃逸分析代码示例

3、逃逸分析失效示例

四、JIT优化之方法内联(Inline Method)

1、概述

2、方法内联示例

3、方法内联的优点

一、关于解释器和编译器



1、概述

Java到底是一门解释型语言还是编译型语言呢?这取决于Java虚拟机,现在主流的商用虚拟机如HotSpot,都同时包含解释器与编译器,我们可以认为Java即是一门解释型语言,也是一门编译型语言。


关于解释器与编译器的优势:


解释器:当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。

编译器:程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地机器码,获取更高的执行效率。


2、JIT(Just In Time)编译器

当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为“热点代码“。为了提高热点代码的执行效率,虚拟机会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(Just In Time Compiler)。


备注:为什么叫HotSpot虚拟机呢?字面意思就是热点虚拟机,其中的一部分功能就是会对热点代码进行优化。

二、JIT优化之锁粗化 & 锁消除



锁粗化锁消除都是针对synchronized平台级锁所做的优化,具体可参考:Java面试题之synchronized关键字原理以及锁相关

三、JIT优化之逃逸分析 & 栈上分配 & 同步消除 & 标量替换



1、概念描述

逃逸分析:所谓逃逸分析简单来说就是,分析创建的对象除了在线程栈中能访问,还能不能被其它线程线程所引用,用于确定创建的对象到底在堆中分配还是栈上分配。


栈上分配:我们都知道对象一般都是在堆上分配,如果逃逸分析发现对象只能在线程栈中访问,则会直接在栈上分配。


同步消除:如果逃逸分析发现一个变量无法被其它线程访问,那这个变量的读写就不会有竞争,对这个变量实施的同步措施也就可以消除掉。比如不保存对象头的Mark Word信息。


标量替换:把对象拆散,将其使用到的成员变量恢复原始类型来访问。如果逃逸分析发现对象只能在当前线程栈中可访问,且对象可以被拆散,那么程序可能不创建这个对象,而是直接在栈上分配成员变量。


备注:所谓标量是指一个数据已经无法再分解成更小的数据来表示了,比如原始数据类型等,都不能再分解,可以称之为标量。如果一个数据可以再分解,我们称作为聚合量,Java中的对象就是最典型的聚合量。

2、逃逸分析代码示例

@Data
class User {
 private Integer id;
 private String name;
}
/**
 * 关闭逃逸分析JVM参数:-XX:-DoEscapeAnalysis
 */
public class EscapeAnalysisExample {
 public static void createUser() {
  User user = new User();
  user.setId(1);
  user.setName("Nick");
 }
 public static void main(String[] args) {
  long start = System.currentTimeMillis();
  for (int count = 0; count < 1024 * 1024 * 50; count++) {
   createUser();
  }
  long end = System.currentTimeMillis();
  System.out.println("耗时为: " + (end - start) + " ms");
 }
}
  • 默认逃逸分析是开启的,运行程序的执行时间为:5ms
  • 加上虚拟机参数-XX:-DoEscapeAnalysis,关闭逃逸分析,运行程序的执行时间为:267ms

3、逃逸分析失效示例

@Data
class User {
 private Integer id;
 private String name;
 private List<String> hobbies = new ArrayList<>();
}


开启逃逸分析,当我们在User类中加上一行代码后,再次执行程序,发现程序执行时间又变成了277ms。

为什么程序的执行时间又会变慢呢?


我们都知道,线程栈的大小是有限的,由虚拟机参数-Xss决定。由于动态集合里无法确定有多少个对象,会占用多少内存,所以此时创建的对象是在堆上分配,而不是在栈上分配。


四、JIT优化之方法内联(Inline Method)



1、概述

关于方法内联的介绍我们在Java官方提供的文档里可以看到,运行时机器码生成器或者优化器会内联final修饰的方法,把方法调用替换成方法体里的代码。6d18aea07b29494ebb1ed0bb91e0f6d2.png

备注:官方文档地址可参考Java语言规范

疑问:是不是只有final方法才有可能在运行时优化被内联呢?


其实并不是的,final方法可以被内联是因为final方法不能被重写,在编译时即可以确定。

除了final方法,非虚方法可以直接被内联,这些方法可以在解析阶段确定唯一的版本。

遇到虚方法,如果该方法只有一个版本(Ps:由于多态可能会有多个版本),也可以进行内联。如果该方法有多个版本,使用内联缓存完成方法内联。

非虚方法定义:静态方法、私有方法、实例构造器、父类方法4类。


虚方法定义:实例方法都是虚方法。


备注:更多关于内联缓存的概念请参考周志明的《深入了解Java虚拟机第2版》。

2、方法内联示例

class Point {
 int x, y;
 void move(int dx, int dy) {
  x += dx;
  y += dy;
 }
}
/**
 * 方法内联示例
 * @author 刘亚楼
 * @date 2022/6/29
 */
public class MethodInlineExample {
 public static void main(String[] args) {
  Point[] points = new Point[1000];
  for (int count = 0; count < points.length; count++) {
   points[count] = new Point();
   points[count].move(count, points.length - 1 - count);
  }
 }
}

上面main方法里的代码会被替换成如下:

public static void main(String[] args) {
 Point[] points = new Point[1000];
 for (int count = 0; count < points.length; count++) {
  points[count] = new Point();
  points[count].x += count;
  points[count].y += points.length - 1 - count;
 }
}

我们都知道方法在调用时会创建一个栈帧(Stack Frame),栈帧中会保存局部变量表,操作数栈,方法出口等信息,每一个方法从调用到执行完成的过程,就代表着一个栈帧在虚拟机栈中入栈到出栈的过程。


通过方法内联,可以减少栈帧的创建,方法调用入栈和出栈的流程,提升程序运行效率。


相关文章
|
2月前
|
安全 Java 编译器
new出来的对象,不一定在堆上?聊聊Java虚拟机的优化技术:逃逸分析
逃逸分析是一种静态程序分析技术,用于判断对象的可见性与生命周期。它帮助即时编译器优化内存使用、降低同步开销。根据对象是否逃逸出方法或线程,分析结果分为未逃逸、方法逃逸和线程逃逸三种。基于分析结果,编译器可进行同步锁消除、标量替换和栈上分配等优化,从而提升程序性能。尽管逃逸分析计算复杂度较高,但其在热点代码中的应用为Java虚拟机带来了显著的优化效果。
59 4
|
2月前
|
数据采集 搜索推荐 Java
Java 大视界 -- Java 大数据在智能教育虚拟学习环境构建与用户体验优化中的应用(221)
本文探讨 Java 大数据在智能教育虚拟学习环境中的应用,涵盖多源数据采集、个性化推荐、实时互动优化等核心技术,结合实际案例分析其在提升学习体验与教学质量中的成效,并展望未来发展方向与技术挑战。
|
4月前
|
缓存 Java 关系型数据库
2025 年最新华为 Java 面试题及答案,全方位打造面试宝典
Java面试高频考点与实践指南(150字摘要) 本文系统梳理了Java面试核心考点,包括Java基础(数据类型、面向对象特性、常用类使用)、并发编程(线程机制、锁原理、并发容器)、JVM(内存模型、GC算法、类加载机制)、Spring框架(IoC/AOP、Bean生命周期、事务管理)、数据库(MySQL引擎、事务隔离、索引优化)及分布式(CAP理论、ID生成、Redis缓存)。同时提供华为级实战代码,涵盖Spring Cloud Alibaba微服务、Sentinel限流、Seata分布式事务,以及完整的D
195 1
|
3月前
|
缓存 Java API
Java 面试实操指南与最新技术结合的实战攻略
本指南涵盖Java 17+新特性、Spring Boot 3微服务、响应式编程、容器化部署与数据缓存实操,结合代码案例解析高频面试技术点,助你掌握最新Java技术栈,提升实战能力,轻松应对Java中高级岗位面试。
331 0
|
8天前
|
Java Spring
如何优化Java异步任务的性能?
本文介绍了Java中四种异步任务实现方式:基础Thread、线程池、CompletableFuture及虚拟线程。涵盖多场景代码示例,展示从简单异步到复杂流程编排的演进,适用于不同版本与业务需求,助你掌握高效并发编程实践。(239字)
101 6
|
13天前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
|
2月前
|
存储 人工智能 算法
Java 大视界 -- Java 大数据在智能医疗影像数据压缩与传输优化中的技术应用(227)
本文探讨 Java 大数据在智能医疗影像压缩与传输中的关键技术应用,分析其如何解决医疗影像数据存储、传输与压缩三大难题,并结合实际案例展示技术落地效果。
|
2月前
|
机器学习/深度学习 算法 Java
Java 大视界 -- Java 大数据机器学习模型在生物信息学基因功能预测中的优化与应用(223)
本文探讨了Java大数据与机器学习模型在生物信息学中基因功能预测的优化与应用。通过高效的数据处理能力和智能算法,提升基因功能预测的准确性与效率,助力医学与农业发展。
|
2月前
|
机器学习/深度学习 算法 Java
Java 大视界 -- Java 大数据在智能物流运输车辆智能调度与路径优化中的技术实现(218)
本文深入探讨了Java大数据技术在智能物流运输中车辆调度与路径优化的应用。通过遗传算法实现车辆资源的智能调度,结合实时路况数据和强化学习算法进行动态路径优化,有效提升了物流效率与客户满意度。以京东物流和顺丰速运的实际案例为支撑,展示了Java大数据在解决行业痛点问题中的强大能力,为物流行业的智能化转型提供了切实可行的技术方案。
|
2月前
|
边缘计算 算法 Java
Java 绿色计算与性能优化:从内存管理到能耗降低的全方位优化策略与实践技巧
本文探讨了Java绿色计算与性能优化的技术方案和应用实例。文章从JVM调优(包括垃圾回收器选择、内存管理和并发优化)、代码优化(数据结构选择、对象创建和I/O操作优化)等方面提出优化策略,并结合电商平台、社交平台和智能工厂的实际案例,展示了通过Java新特性提升性能、降低能耗的显著效果。最终指出,综合运用这些优化方法不仅能提高系统性能,还能实现绿色计算目标,为企业节省成本并符合环保要求。
82 0

热门文章

最新文章