JVM逃逸分析与栈上分配的原理
解释JVM的逃逸分析(Escape Analysis)技术原理,包括对象是否逃逸的判断依据、栈上分配(Stack Allocation)的触发条件、标量替换(Scalar Replacement)和同步消除的实现。
回答
屠龙少年
1. 逃逸分析基本原理
- JVM通过分析对象的作用域,判断对象是否逃逸出方法/线程
- 开启参数:
-XX:+DoEscapeAnalysis(JDK 8+默认开启)
三种逃逸状态:
- NoEscape(不逃逸):对象仅在方法内创建和使用
- ArgEscape(方法参数逃逸):对象作为参数传递但未全局逃逸
- GlobalEscape(全局逃逸):对象赋值给静态变量或作为方法返回值
2. 优化手段 栈上分配(Stack Allocation):
- 不逃逸的对象直接在栈帧中分配
- 方法结束后自动出栈,无需GC介入
- 必须以
-XX:+EliminateAllocations开启
标量替换(Scalar Replacement):
- 将对象的字段分解为独立的标量(原始类型)
- 对象本身的堆分配被完全消除
// 原始代码
Point p = new Point(x, y); // Point不会逃逸
int sum = p.x + p.y;
// 标量替换后
int sum = x + y; // 堆分配被消除
同步消除(Lock Elimination):
- 不逃逸对象上的同步操作被消除
-XX:+EliminateLocks
3. 触发条件
- Server模式下(
-server) - 分层编译级别达到C2(编译阈值约10000次调用)
- 对象足够小(太大仍会在TLAB中分配)
4. 查看分析结果
-XX:+PrintEscapeAnalysis:输出逃逸分析-XX:+PrintEliminateAllocations:输出标量替换日志