什么是逃逸分析?它的作用是什么?代码举例讲解

逃逸分析(Escape Analysis)是Java虚拟机对对象动态作用域的分析,它可以判断一个对象的作用域是否超出了方法或者线程。根据分析结果,JVM会选择将对象分配在栈上还是堆上。

逃逸分析的作用是:

  1. 如果对象的作用域被限定在方法或线程内,那么将其分配在栈上,可以减少GC负担,提高性能。
  2. 如果对象可能逃逸到方法或线程之外,那么还是分配在堆上,以确保对象可以被更广范围地访问。
  3. 逃逸分析可以带来内存上的优化,但是对代码性能的影响较小。

在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) {
    // ...  
} 

在该示例中:

  1. e1的作用域限定在方法内,经逃逸分析后分配在栈上。
  2. e2通过赋值逃逸到方法外,分配在堆上。
  3. e3在新线程中使用,发生线程逃逸,分配在堆上。
  4. 对象分配在栈上节省GC代价,性能略有提升。

所以,逃逸分析可以带来一定的性能提升,但是对代码性能影响有限。