JVM的内存分配规则中,对象默认分配在堆上,由垃圾回收器负责回收,但逃逸分析优化打破了这个默认规则,让部分局部对象可以直接分配在栈上,随方法栈帧的出栈自动销毁,不需要垃圾回收介入。

什么是逃逸分析
逃逸分析是JVM在即时编译(JIT)阶段执行的一项优化分析,核心作用是判断新创建的对象的作用范围是否会逃逸出当前方法或者当前线程。如果对象的作用范围完全局限在方法内部,没有被外部方法引用,也没有被其他线程访问到,就称这个对象没有发生逃逸,此时JVM就可以对这个对象做一系列优化,栈上分配就是其中一项核心优化。
逃逸的两种常见场景
- 方法逃逸:对象被作为返回值返回,或者被作为参数传递到了其他方法,导致对象的作用范围超出了当前方法。
- 线程逃逸:对象被赋值给了类变量,或者被其他线程通过共享变量访问到,导致对象的作用范围超出了当前线程。
为什么无逃逸对象可以栈上分配
栈上的内存分配和回收效率远高于堆:栈帧是线程私有的,方法执行时创建栈帧,栈帧中包含局部变量表、操作数栈等空间,方法执行结束后栈帧直接出栈销毁,不需要额外的垃圾回收操作。而堆上的对象需要垃圾回收器判断存活状态,回收过程会消耗一定的性能。
如果逃逸分析判定对象没有发生逃逸,JVM就可以把这个对象的实例数据直接分配在当前方法的栈帧中,而不是堆上。当方法执行结束,栈帧销毁,这个对象占用的内存也直接被释放,完全不需要垃圾回收介入,能显著降低堆内存的分配压力和垃圾回收的频率。
代码示例验证逃逸分析与栈上分配
我们可以通过一段简单的代码来观察无逃逸对象的分配情况,首先需要开启JVM的逃逸分析相关参数,JDK 1.7之后逃逸分析是默认开启的,也可以手动指定参数:
// 逃逸分析相关JVM参数
// -XX:+DoEscapeAnalysis 开启逃逸分析(默认开启)
// -XX:-DoEscapeAnalysis 关闭逃逸分析
// -XX:+PrintGCDetails 打印垃圾回收详情
public class EscapeAnalysisTest {
public static void main(String[] args) {
long start = System.currentTimeMillis();
// 循环调用创建对象的方法
for (int i = 0; i < 100000000; i++) {
createNoEscapeObject();
}
long end = System.currentTimeMillis();
System.out.println("执行耗时:" + (end - start) + "ms");
// 防止程序提前退出,方便观察GC情况
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 创建的对象只在方法内部使用,没有逃逸
private static void createNoEscapeObject() {
// 局部对象,没有返回,也没有传递给其他方法
User user = new User("test", 18);
// 仅方法内部使用对象属性,没有外部引用
int age = user.getAge();
}
static class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
}
}
当我们开启逃逸分析运行上述代码时,会发现执行耗时很短,并且几乎不会产生垃圾回收日志,因为User对象没有发生逃逸,全部在栈上分配,随方法栈帧出栈直接销毁。如果关闭逃逸分析,对象会全部分配在堆上,会频繁触发垃圾回收,执行耗时也会明显增加。
逃逸分析的其他优化
除了栈上分配,逃逸分析还会触发另外两项优化:
- 标量替换:如果对象没有逃逸,JVM可能不会创建完整的对象结构,而是把对象的成员变量拆分成独立的标量(比如int、reference等),直接分配在栈上的局部变量表中,进一步减少内存占用。
- 同步消除:如果对象没有发生线程逃逸,说明不会有多个线程同时访问这个对象,那么对象上的同步锁(比如
synchronized修饰的代码块)就可以被消除,减少同步带来的性能开销。
注意事项
逃逸分析的优化并不是绝对的,JVM会根据运行时的实际情况判断是否执行优化。另外,栈的容量是有限的,如果对象占用的内存过大,即使没有逃逸,JVM也可能不会选择栈上分配,而是继续分配在堆上。开发者在写代码时,可以尽量缩小对象的作用范围,避免不必要的对象逃逸,让JVM更好地执行优化,提升程序性能。
JVM逃逸分析Escape_Analysis栈上分配修改时间:2026-07-03 23:27:36