聊聊逃逸分析
什么是逃逸技术
逃逸分析技术是JVM
用于提高性能以及节省内存的手段,在JVM
编译语境下(JIT阶段)
,逃逸分析通过以下两个条件判断该对象是否是逃逸的:
- 该对象是否分配在堆上(
static
关键字或者成员变量) - 该对象是否会传给未知代码,比如
return
到外部给别的类使用。
逃逸技术的两个示例
如下所示,这两段代码就是典型的情况2,将对象传给未知代码,造成逃逸
java
/**
* @author binghe
* @description 对象逃逸示例2
*/
public class ObjectReturn{
public User createUser(){
User user = new User();
return user;
}
}
逃逸分析带来的好处
对象可能分配在栈上
JVM
会判断这个对象使用范围,若没有发生逃逸则将对象分配在栈上,这样做的好处就是创建销毁速度会相对快些,而且节省堆区内存,避免GC开销。
分离对象或标量替换
由上文我们知道,对象有可能会被分配在栈上,那么JVM
就会将这个对象打散,将对象打散为无数个小的局部变量,这样就方便在栈上分配内存了。
如下所示,若这段代码没有发生逃逸,则JVM
会避免创建Point
java
public static void main(String args[]) {
alloc();
}
class Point {
private int x;
private int y;
}
private static void alloc() {
Point point = new Point(1,2);
System.out.println("point.x" + point.x + ";point.y" + point.y);
}
代码就会被标量替换,如下所示,避免创建对象,而是用局部变量进行操作。
java
private static void alloc() {
int x = 1;
int y = 2;
System.out.println("point.x = " + x + "; point.y=" + y);
}
同步锁消除
如果JVM
分析到这个锁只有一个对象会用到就会将这个锁消除。如下代码JVM
看到是字符串拼接操作,就会优化为使用到StringBuffer
或StringBuilder
。
bash
public static String test03(String s1, String s2, String s3) {
String s = s1 + s2 + s3;
return s;
}
经过逃逸分析发现,是无锁竞争环境,就使用StringBuilder
,如下所示