1、逃逸分析
逃逸分析是为JVM的GC优化提供的一种分析技术,用来判断一个变量的作用域;
-
方法逃逸
一个变量的作用域不仅限于当前方法;
-
线程逃逸
一个变量的作用域不仅限于当前线程;目前线程逃逸还是无法进行优化的;
![202301011642047441.png][]
2、栈上分配
- 创建的对象是在栈上分配内存,而不是在堆上分配,当方法执行完之后,占用的内存随着栈帧的弹出而被回收;
- 栈上分配目前只能优化方法逃逸,无法优化线程逃逸;
- 参数-XX:+DoEscapeAnalysis开启逃逸分析(JDK8默认开启),-XX:-DoEscapeAnalysis关闭逃逸分析;
- 实例:
- ![202301011642052032.png][]
- ![202301011642058483.png][]
3、标量替换
-
所谓标量,可以理解为原子的,就是不能够再进行分解,在java中的基本数据类型就是标量;与标量相对应的就是聚合量,比如一个对象;
-
标量替换就是把对象中的成员变量根据访问情况来使用标量进行替换,并将其放入栈帧的局部变量表中;而并不去真正的创建这个对象;
-
参数-XX:+EliminateAllocations开启标量替换(JDK8默认开启);
-
实例(伪代码) *``` //经过逃逸分析,user没有发生逃逸 public static int escapeTest(){ int age = 20; User user = new User(); user.setAge(age); user.setName("23"); return user.getAge(); }
//内联优化 public static int escapeTest(){ int age = 20; User user = new User(); user.age = age user.name = "23"; return user.age; } //开启了标量替换,则使用标量替换 public static int escapeTest(){ int age = 20; int userAge = age int userName = "23"; return userAge; } //发现userAge、userName对方法毫无影响,因此可以去掉 public static int escapeTest(){ int age = 20; return age; }
#### 4、同步消除 ####
* 如果逃逸分析能够确定一个变量不会发生线程逃逸,那么该变量的读写肯定不会存在竞争,因此可以取消该变量的同步锁,同步本身就是一个耗时的操作,通过消除,提升性能;
* 本质上是把同步锁改成了偏向锁;
* 参数-XX:+EliminateLocks开启同步消除(JDK8默认开启);
* 实例
* ![202301011642065454.png][]
* ![202301011642073175.png][]
常用参数:
-XX:DoEscapeAnalysis //是否开启逃逸分析(是否允许栈上分配) +:开启,-:禁用
-XX:EliminateAllocations //是否开启标量替换(在开启逃逸分析的基础上) +:开启,-:禁用
-XX:EliminateLocks //是否开启同步消除(在开启逃逸分析的基础上) +:开启,-:禁用
[202301011642047441.png]: http://image.skjava.com/article/common/2023/1/202301011642047441.png
[202301011642052032.png]: http://image.skjava.com/article/common/2023/1/202301011642052032.png
[202301011642058483.png]: http://image.skjava.com/article/common/2023/1/202301011642058483.png
[202301011642065454.png]: http://image.skjava.com/article/common/2023/1/202301011642065454.png
[202301011642073175.png]: http://image.skjava.com/article/common/2023/1/202301011642073175.png