JVM底层原理之什么是逃逸分析
【jvm|JVM底层原理之什么是逃逸分析】介绍:
逃逸分析(Escape Analysis)根据运行状态可以判断方法中的变量 , 是否会被外部方法引用或外部线程访问 , 如果会 , 那么这个行为就是逃逸 , 根据情况可以分为两种逃逸:
方法逃逸
当一个方法中的变量可能被外部方法所引用 , 比方说作为调用参数 , 将其传递到其他的子方法中 , 这种可以称为方法逃逸 。
线程逃逸
如果是多线程环境 , 有的变量没有作线程保护 , 可能会被外部线程访问到 , 这种行为称为线程逃逸 。
也就是这项技术并不是什么优化技术 , 而是进行某些专项优化前的必要分析 , 如果不会发生逃逸现象 , 才进行一些专项的优化 。 另外这项技术是从JDK1.6开始的 , 所以目前而言不算太成熟 , 因为逃逸分析需要一些复杂的运算 , 又要兼顾性能的损耗 , 所以会有一些误差 。
参数设置:
可以通过JVM参数进行设置开启或关闭逃逸分析:
-XX:+DoEscapeAnalysis 开启逃逸分析(jdk1.8 默认开启)-XX:-DoEscapeAnalysis 关闭逃逸分析
它手下的优化方法主要有三种:栈上分配
、锁消除
、标量替换
。 也就是如果你没开启逃逸分析 , 那么就相当于关闭了这三种优化手段了 。
a.栈上分配(Stack Allocations)如果确定一个变量不会逃逸出方法外 , 那么C2会让这个对象直接在栈上分配内存创建实例 , 而不是在堆上 , 因为这样一来可以加快速度 , 二来是该变量占用的内存空间可以随着栈帧出栈而销毁 。
一般应用中 , 大多局部对象都可以使用栈上分配 , 这样垃圾收集器的压力就会小很多 。
b.同步消除(Synchronization Elimination)又名锁消除 , 多线程的情况下 , 有些变量会上同步锁 , 避免发生线程冲突问题 。 但是经过了逃逸分析后 , 该变量分析确定了它不会逃逸出线程 , 不会被其他线程访问到 , 那这个变量就没有必要上什么同步锁了 , 就可以清除掉这个变量的同步锁以节约资源 。
比较常用的例子是StringBuffer的append()方法 , 由于加了修饰符synchronized , 所以是线程安全的 , 但是如果你是单线程环境 , 就完全没有必要上这个锁了 。 所以开启了逃逸分析和锁消除的情况下(还要是C2才行) , 优化时就会将同步锁清除 , 大大的提升效率 。
参数:
-XX:+EliminateLocks 开启锁消除(jdk1.8 默认开启)-XX:-EliminateLocks 关闭锁消除
c.标量替换(Scalar Replacement)标量(Scalar)是指一个数据已经无法再分解成更小的数据来表示了 , Java中的原始数据类型(int、long等数值类型以及reference类型等)不能在进一步分解 , 这些就可以称为标量 。
如果把一个Java对象拆散 , 根据程序访问的情况 , 将其使用到的成员变量恢复原始类型来访问就叫做标量替换 。
聚合量:
相对的 , 如果一个数据可以继续分解 , 那它就称作聚合量(Aggregate) , Java中的Object对象就是最典型的聚合量 。
如果逃逸分析证明一个对象不会被外部访问的话 , 在优化时就可能进行标量替换 。 也就是在程序执行时 , 将不会创建整个对象 , 而是拆分为只创建它使用到的几个成员变量的标量 。 将对象拆分后 , 还可能结合栈上分配 , 将这些基本标量直接在栈上创建实例 , 可以为后续进一步的优化手段创建条件 。
这里用java语言举个例子 , 当然实际情况jvm是直接读取class文件的:
public void test() {
\t\tUserInfo user = new UserInfo();
\t\tuser.id = 1;
\t\tuser.age = 18;
\t
经过标量替换:
public void test() {\t\tint id = 1;\t\tint age = 18;
\t
大概就是这么个意思 , 这样可以节省很多不必要的内存空间
参数:
-XX:+EliminateAllocations 开启标量替换(jdk1.8 默认开启)-XX:-EliminateAllocations 关闭就可以了
逃逸分析的缺陷逃逸分析在JDK1.6中不太成熟 , 主要是不能保证逃逸分析的性能收益必定高于它的消耗 。 如果要完全准确地判断一个对象是否会逃逸 , 需要进行一系列的复杂分析 , 但是这样会很消耗资源 , 如果分析完后没有什么收获 , 就相当于凭空浪费了很多资源 。 所以目前虚拟机采用的是不那么准确 , 但时间压力相对较小的算法来完成逃逸分析 。
- 新浪VR|底层技术深度打磨 ColorOS为Reno8带来持久流畅体验
- jvm|Java:了解JVM加载、JVM链接和JVM初始化
- jvm|JVM底层原理之JIT编译器如何通过方法内联优化代码
- jvm|有人把天玑9000吹过头了
- jvm|JVM底层原理之如何选用C1、C2编译器?它们有什么区别?
- jvm|小米推出具有惊人功能的8H手感皮革智能电动床X Pro
- jvm|五一准备换电脑?恰好神舟战神笔记本也放“价”
- jvm|OPPO K10、OPPO K10 Pro怎么选?一文带你详细了解
- jvm|3199的OPPOK10Pro对比2499的K10,差价是由哪些东西带来的?
- jvm|那款一抬腕,就知前方路线的Apple Watch你有了吗?