JVM 逃逸分析技术

简介: 逃逸分析技术的日渐成熟,促使所有的Java对象实例不一定都在Java堆上分配内存简单来讲就是,Java Hotspot 虚拟机可以分析新创建对象的使用范围,并决定是否在 Java 堆上分配内存的一项技术。

网络异常,图片无法展示
|


简介

逃逸分析技术的日渐成熟,促使所有的Java对象实例不一定都在Java堆上分配内存

简单来讲就是,Java Hotspot 虚拟机可以分析新创建对象的使用范围,并决定是否在 Java 堆上分配内存的一项技术。

使用

  • 开启逃逸分析:-XX:+DoEscapeAnalysis
  • 关闭逃逸分析:-XX:-DoEscapeAnalysis
  • 显示分析结果:-XX:+PrintEscapeAnalysis
  • 逃逸分析技术在 Java SE 6u23+ 开始支持,并默认设置为启用状态

逃逸程度

逸分析的基本行为就是分析对象动态作用域,从不逃逸方法逃逸线程逃逸,称为对象由低到高的不同逃逸程度

方法逃逸

当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他地方中,称为方法逃逸

/*StringBuffer sb是一个方法内部变量,上述代码中直接将sb返回,这样这个StringBuffer有可能被其他方法所
*改变,这样它的作用域就不只是在方法内部,虽然它是一个局部变量,称其逃逸到了方法外部。甚至还有可能被外部线
*程访问到,譬如赋值给类变量或可以在其他线程中访问的实例变量,称为线程逃逸。
*/
 public static StringBuffer craeteStringBuffer(String s1, String s2) {
     StringBuffer sb = new StringBuffer();
     sb.append(s1);
     sb.append(s2);
     return sb;
 }
 //上述代码如果想要StringBuffer sb不逃出方法,可以这样写:
 public static String createStringBuffer(String s1, String s2) {
     StringBuffer sb = new StringBuffer();
     sb.append(s1);
     sb.append(s2);
     return sb.toString();
 }

线程逃逸

  • 当一个对象在方法中被定义后,它可能被外部线程访问到,譬如赋值给可以在其他线程中访问的实例变量,这种称为线程逃逸

逃逸分析优化

如果能证明一个对象不会逃逸到方法或线程之外(换句话说是别的方法或线程无法通过任何途径访问到这个对象),或者逃逸程度比较低(只逃逸出方法而不会逃逸出线程),则可能为这个对象实例采取不同程度的优化

栈上分配(Stack Allocations)

  • 如果确定一个对象不会逃逸出线程之外,那让这个对象在栈上分配内存将会是一个很不错的主意,对象所占用的内存空间就可以随栈帧出栈而销毁
  • 由于复杂度等原因,HotSpot中目前暂时还没有做这项优化,但一些其他的虚拟机(如Excelsior JET)使用了这项优化。
  • 栈上分配可以支持方法逃逸,但不能支持线程逃逸。

标量替换(Scalar Replacement)

  • 若一个数据已经无法再分解成更小的数据来表示了,Java虚拟机中的原始数据类型(int、long等数值类型及reference类型等)都不能再进一步分解了,那么这些数据就可以被称为标量。相对的,如果一个数据可以继续分解,那它就被称为聚合量(Aggregate),Java中的对象就是典型的聚合量。
  • -XX:+EliminateAllocations 开启标量替换(jdk8默认开启)
  • -XX:+PrintEliminateAllocations 查看标量的替换情况
  • 如果把一个Java对象拆散,根据程序访问的情况,将其用到的成员变量恢复为原始类型来访问,这个过程就称为标量替换
  • 假如逃逸分析能够证明一个对象不会被方法外部访问,并且这个对象可以被拆散,那么程序真正执行的时候将可能不去创建这个对象,而改为直接创建它的若干个被这个方法使用的成员变量来代替。
  • 标量替换可以视作栈上分配的一种特例,实现更简单(不用考虑整个对象完整结构的分配),但对逃逸程度的要求更高,它不允许对象逃逸出方法范围内

同步消除(Synchronization Elimination)

也叫锁消除

  • +XX:+EliminateLocks 开启同步消除(jdk8默认开启)
  • 线程同步本身是一个相对耗时的过程,如果逃逸分析能够确定一个变量不会逃逸出线程,无法被其他线程访问,那么这个变量的读写肯定就不会有竞争,对这个变量实施的同步措施也就可以安全地消除掉
  • 比如常用的线程安全类:StringBuffer,HashTable,Vector等.
相关文章
|
19天前
|
监控 Oracle Java
《深入浅出Java虚拟机 — JVM原理与实战》带你攻克技术盲区,探索各大JVM虚拟机特色 —— JVM故障排除指南(先导篇)
《深入浅出Java虚拟机 — JVM原理与实战》带你攻克技术盲区,探索各大JVM虚拟机特色 —— JVM故障排除指南(先导篇)
47 0
|
19天前
|
缓存 算法 安全
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(二)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
24 0
|
19天前
|
缓存 Java C#
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(一)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
98 0
|
3天前
|
存储 安全 Java
深入探究Java虚拟机(JVM)的技术细节
深入探究Java虚拟机(JVM)的技术细节
|
19天前
|
算法 Java
深入浅出JVM(十六)之三色标记法与并发可达性分析
深入浅出JVM(十六)之三色标记法与并发可达性分析
|
19天前
|
存储 Arthas 监控
JVM工作原理与实战(三十):堆内存状况的对比分析
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了堆内存状况的对比分析、产生内存溢出的原因等内容。
16 0
|
19天前
|
监控 算法 安全
JVM工作原理与实战(二十三):堆的垃圾回收-引用计数法和可达性分析法
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了判断堆上的对象是否可以回收的方法(引用计数法、可达性分析法)、查看垃圾回收日志等内容。
16 0
|
19天前
|
存储 监控 安全
21个 JVM 技术点详解(附面试解答)
以上V哥给大家详细介绍了 JVM 中涉及的21个点,全网还没有针对 JVM 这样来梳理的内容,希望对你深入了解 JVM 有一定帮助,另,V 哥给大家推荐一本《深入 JVM 虚拟机》的书籍,可以作为工具书使用,高阶的 Java 程序员几乎人手一本。今天的分享就到这里,任何疑问欢迎与 V 哥一起交流,畅谈 Java 人生。
|
19天前
|
算法 安全 Java
【JVM】并发的可达性分析详细解释
【JVM】并发的可达性分析详细解释
|
19天前
|
监控 Java 调度
探秘Java虚拟机(JVM)性能调优:技术要点与实战策略
【4月更文挑战第17天】本文探讨了JVM性能调优的关键技术,包括内存模型调优(关注堆内存和垃圾回收),选择和优化垃圾收集器,利用JVM诊断工具进行问题定位,以及实战调优案例。强调了开发者应理解JVM原理,善用工具,结合业务场景进行调优,以应对高并发和大数据量的挑战。调优是持续的过程,能提升系统稳定性和效率。