逃逸分析
(1)逃逸分析: 当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他地方中,称为方法逃逸。
(2)使用逃逸分析,JIT编译器可以对代码优化:
1)同步省略: 如果一个同步代码块中的对象被加了锁,但这个对象只在方法中定义并调用,没有逃逸,那么JIT编译器会把同步代码 块变成正常的代码块,这就叫同步省略,又叫锁消除。
例如:
public void f() {
Object hollis = new Object();
synchronized(hollis) {
System.out.println(hollis);
}
}
hollis 对象的作用域只在f() 方法中,所以会被优化成:
public void f() {
Object hollis = new Object();
System.out.println(hollis);
}
2)标量替换: 标量(Scalar)是指一个无法再分解成更小的数据的数据。Java中的原始数据类型就是标量。相对的,那些还可以分 解的数据叫做聚合量(Aggregate),Java中的对象就是聚合量,因为他可以分解成其他聚合量和标量。在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;
}
被优化成:
private static void alloc() {
int x = 1;
int y = 2;
System.out.println("point.x="+x+"; point.y="+y);
}
栈上分配
如果经过逃逸分析后发现,一个对象并没有逃逸出方法的话,那么就可能被优化成栈上分配。
其实在现有的虚拟机中,并没有真正的实现栈上分配,但也没有在堆上分配,其实是标量替换实现的。