逃逸分析简介

逃逸分析定义:一种确定指针动态范围的静态分析,它可以分析在程序的哪些地方可以访问到指针。

逃逸分析并不是直接的优化手段,而是一个代码分析,通过动态分析对象的作用域,为其它优化手段如栈上分配标量替换同步消除(也叫同步省略)等提供依据,发生逃逸行为的情况有两种:方法逃逸线程逃逸

  • 方法逃逸:当一个对象在方法中定义之后,作为参数传递到其它方法中;
    方法逃逸:
public static User createUser(){User user = new User();user.setId(713);user.setName("zl");user.setAge(18);return user;
}

非方法逃逸:

public static void createUser(){User user = new User();user.setId(713);user.setName("zl");user.setAge(18);
}public static String createUser(){User user = new User();user.setId(713);user.setName("zl");user.setAge(18);//User要实现get,set方法,还要实现toString方法return user.toString();
}
  • 线程逃逸:如类变量或实例变量,可能被其它线程访问到;

启用/关闭逃逸分析

-XX:+DoEscapeAnalysis : 表示开启逃逸分析
-XX:-DoEscapeAnalysis : 表示关闭逃逸分析

从jdk 1.7开始已经默认开始逃逸分析,如需关闭,需要指定-XX:-DoEscapeAnalysis

-XX:+PrintEscapeAnalysis来查看分析结果。

使用下面代码测试启动和关闭逃逸分析。

public static void main(String[] args) {long startTime = System.currentTimeMillis();EscapeAnalysisTest test = new EscapeAnalysisTest();test.createUser();System.out.println("代码执行完毕!耗时:"+(System.currentTimeMillis()-startTime)+"ms");}public void createUser(){int i=0;while (true){User user = new User();user.setId(i++);user.setName("zl");user.setAge(20);if (i>100000000) {break;}}}

启动逃逸分析

在启动参数中增加参数:

-XX:+PrintGC -XX:+DoEscapeAnalysis

运行输出:

程序并没有出现GC的情况,说明逃逸分析生效,User字段数据在栈上分配。并且程序运行只需要10ms。

关闭逃逸分析

在启动参数中增加参数:

-XX:+PrintGC -XX:-DoEscapeAnalysis


程序并出现GC的情况,说明 对象在堆上分配,并且出现GC回收User对象。并且耗时需要520ms,即便关闭gc打印,也需要470ms,远比开启逃逸分析要慢。

JVM性能优化手段

如果不存在逃逸行为,则可以对该对象进行如下优化:同步消除、标量替换和栈上分配。

同步消除

如果一个对象被发现只能从一个线程被访问到,那么对于这个对象的操作可以不考虑同步。

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

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

可以通过-XX:+EliminateLocks可以开启同步消除。

标量替换

标量即不可被进一步分解的量,而Java的基本数据类型就是标量(比如int,long等基本数据类型以及reference类型等),标量的对立就是可以被进一步分解的量,而这种量称之为聚合量。而在Java中对象就是可以被进一步分解的聚合量。

通过逃逸分析确定该对象不会被外部访问,并且对象可以被进一步分解时,JVM不会创建该对象,而是将该对象成员变量分解若干个被这个方法使用的成员变量所代替,这些代替的成员变量在栈帧或寄存器上分配空间,这样就不会因为没有一大块连续空间导致对象内存不够分配。

通过-XX:+EliminateAllocations可以开启标量替换(JDK7之后默认开启)。
通过-XX:+PrintEliminateAllocations查看标量替换情况。

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

public static void main(String[] args) {alloc();
}private static void alloc() {Point point = new Point(1,2);System.out.println("point.x="+point.x+"; point.y="+point.y);
}
class Point{private int x;private int y;
}

以上代码中,point对象并没有逃逸出alloc方法,并且point对象是可以拆解成标量的。那么,JIT就会不会直接创建Point对象,而是直接使用两个标量int x ,int y来替代Point对象。

替换后:

private static void alloc() {int x = 1;int y = 2;System.out.println("point.x="+x+"; point.y="+y);
}

这种替换可以大大减少堆内存的占用,因为一旦不需要创建对象了,那么就不需要分配堆内存了。

栈上分配

Java虚拟机中,在Java堆上分配创建对象的内存空间几乎是Java程序员都清楚的常识了,Java堆中的对象对于各个线程都是共享和可见的,只要持有这个对象的引用,就可以访问堆中存储的对象数据。

虚拟机的垃圾收集系统可以回收堆中不再使用的对象,但回收动作无论是筛选可回收对象,还是回收和整理内存都需要耗费时间。

如果确定一个对象不会逃逸出方法之外,那让这个对象在栈上分配内存将会是一个很不错的主意,对象所占用的内存空间就可以随栈帧出栈而销毁。

在一般应用中,不会逃逸的局部对象所占的比例很大,如果能使用栈上分配,那大量的对象就会随着方法的结束而自动销毁了,垃圾收集系统的压力将会小很多。

故名思议就是在栈上分配对象,其实目前Hotspot并没有实现真正意义上的栈上分配,实际上是标量替换。

参考:https://blog.csdn.net/qq_31960623/article/details/120178489

JVM-逃逸分析浅析相关推荐

  1. JVM 逃逸分析 (史上最全)

    对于JVM"逃逸分析" 特性,也是近年来大厂面试.高薪面试的常见面试题. 和逃逸分析有关的常见面试题: Java中的对象一定是在堆上分配的吗? 注:本文以 PDF 持续更新,最新尼 ...

  2. JVM逃逸分析(同步省略、标量替换、栈上分配)

    在Java的编译体系中,一个Java的源代码文件变成计算机可执行的机器指令的过程中,需要经过两段编译,第一段是把.java文件转换成.class文件.第二段编译是把.class转换成机器指令的过程. ...

  3. 深入理解JVM逃逸分析

    本文来说下JVM中的逃逸分析 文章目录 JIT 逃逸分析 同步消除 标量替换 栈上分配 编译阈值 本文小结 JIT 即时编译(Just-in-time Compilation,JIT)是一种通过在运行 ...

  4. 深入分析JVM逃逸分析对性能的影响

    逃逸分析(Escape Analysis) 逃逸分析的基本行为就是分析对象动态作用域:当一个对象在方法中被定义后,它可能被外部方法所引用,称为方法逃逸.甚至还有可能被外部线程访问到,譬如赋值给类变量或 ...

  5. 【Task】- JVM逃逸分析等待学习任务

    Tiered Compilation Compressed Oops Zero-Based Compressed Oops Escape Analysis NUMA Collector Enhance ...

  6. Java - 深入理解Java中的逃逸分析

    在Java的编译体系中,一个Java的源代码文件变成计算机可执行的机器指令的过程中,需要经过两段编译,第一段是把.java文件转换成.class文件.第二段编译是把.class转换成机器指令的过程. ...

  7. 如果面试官问你 JVM,额外回答逃逸分析技术会让你加分!

    我在面试别人的过程中,JVM 内存模型我几乎必问,虽然有人说问这些就是面试造航母,工作拧螺丝.如果你想当一名 CRUD 码农,你可以选择不用了解这些. 在 JVM 内存模型的问答中,有些人能说出对象是 ...

  8. JVM【带着问题去学习 01】什么是JVM+内存结构+堆内存+堆内存参数(逃逸分析)

    1.是什么 (1) 基本概念:可运行 Java 代码的非真实计算机 ,包括一套字节码指令集.一组寄存器.一个栈.一个垃圾回器,堆和一个存储方法域.它运行在操作系统之上,与硬件没有直接的交互. (2) ...

  9. JVM学习笔记之-堆,年轻代与老年代,对象分配过程,Minor GC、Major GC、Full GC,堆内存大小与OOM,堆空间分代,内存分配策略,对象分配内存,小结堆空间,逃逸分析,常用调优工具

    堆的核心概述 概述 一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域.Java堆区在JVM 启动的时候即被创建,其空间大小也就确定了.是JVM管理的最大一块内存空间. 堆内存的大小是可 ...

  10. 小师妹学JVM之:逃逸分析和TLAB

    文章目录 简介 逃逸分析和栈上分配 TLAB简介 TLAB详解 设置TLAB空间的大小 TLAB中大对象的分配 TLAB空间中的浪费 总结 简介 逃逸分析我们在JDK14中JVM的性能优化一文中已经讲 ...

最新文章

  1. [linux][c语言]用socket实现简单的服务器客户端交互
  2. 区块链架构下 智慧城市发展加速
  3. 程序员出身,身价 340 亿!没有他,可能我们刷不了 B 站
  4. C++五子棋(四)——走棋原理及权值计算
  5. c语言实现天气预报步骤,天气预报是怎么预测天气的?天气预报制定需要哪些步骤...
  6. Java中String字符串toString()、String.valueOf()、String强转、+ 的区别
  7. Onboard,迷人的引导页样式制作库
  8. [bbk2228] 第41集 - Chapter 11-SQL Statement Tuning(00)
  9. nodejs连接数据库的增删改查
  10. 亿安科技作手_亿安科技作手(2)-李B
  11. Linux vi命令修改文件内容笔记
  12. 地址后面的sessionid怎么消除_大朗饭店消除蟑螂帮您识别隐蔽鼠迹
  13. 淘宝/天猫API:item_search_jupage-天天特价
  14. 面试必问JavaScript基础面试题(附答案详解)
  15. 读计算机网络得学五笔吗,打破无聊难学 另类五笔学习方法
  16. 浅谈RASP技术攻防之实战
  17. 微博数据解析:国产彩妆品牌对比 | 完美日记 VS 花西子
  18. 笔记本麦克风声音小解决办法
  19. 【笔试】京东数据分析暑期实习
  20. 浅析“高内聚,低耦合”

热门文章

  1. python表情代码_Python实现表情包的代码实例
  2. VS2019:scanf返回值被忽略
  3. php cacti,cacti搭建遇到的那些事
  4. Flex ExternalInterface调用javascript
  5. 港股直通车“鸣笛”4000亿资金或被分流
  6. IP不是万能药 为何有蜘蛛侠等大片的索尼要放弃电影
  7. css实现自定义虚线边框
  8. 书城项目第六、七阶段
  9. python中输入字符串_简单讲解Python中的字符串与字符串的输入输出
  10. 阿里云IOT C-SDK 源码分析系列(1):应用框架概述