逃逸分析(Escape Analysis)是Java虚拟机对对象动态作用域的分析,它可以判断一个对象的作用域是否超出了方法或者线程。根据分析结果,JVM会选择将对象分配在栈上还是堆上。
逃逸分析的作用是:
- 如果对象的作用域被限定在方法或线程内,那么将其分配在栈上,可以减少GC负担,提高性能。
- 如果对象可能逃逸到方法或线程之外,那么还是分配在堆上,以确保对象可以被更广范围地访问。
- 逃逸分析可以带来内存上的优化,但是对代码性能的影响较小。
在JDK 6之前,所有对象都分配在堆上。从JDK 6开始,HotSpot JVM引入了逃逸分析,可以将一些作用域被限定的对象分配在栈上。
JVM中通过如下参数可以指定是否开启逃逸分析
-XX:+DoEscapeAnalysis :开启逃逸分析(JDK 1.7之后默认开启)
-XX:-DoEscapeAnalysis :关闭逃逸分析
来看一个简单示例:
public void escapeAnalysis() {
// 未发生逃逸,分配在栈上
Employee e1 = new Employee();
// 发生逃逸,分配在堆上
Employee e2 = new Employee();
e2 = e3;
// 发生逃逸,分配在堆上
Employee e3 = new Employee();
new Thread() {
public void run() {
use(e3);
}
}.start();
}
public void use(Employee e) {
// ...
}
在该示例中:
- e1的作用域限定在方法内,经逃逸分析后分配在栈上。
- e2通过赋值逃逸到方法外,分配在堆上。
- e3在新线程中使用,发生线程逃逸,分配在堆上。
- 对象分配在栈上节省GC代价,性能略有提升。
所以,逃逸分析可以带来一定的性能提升,但是对代码性能影响有限。