栈上分配

通过jvm内存分配可以知道java中的对象都是在堆中进行分配的, 当对象没有被引用的时候, 需要依靠gc进行回收内存, 如果对象数量较多的时候, 会给gc带来较大的压力, 也间接影响了应用的性能.为了减少临时对象在堆内分配的数量, jvm通过逃逸分析确定该对象会不会对外部访问.如果不会逃逸可以将该对象在栈上分配.这样的话该对象所占用的内存空间就可以随着栈帧出栈而销毁, 就减轻了垃圾回收的压力.

对象逃逸分析

就是分析该对象动态的作用域, 当一个对象在方法中被定义后, 他可能被外部方法所引用.例如作为参数传递到其他方法中.

jdk7之后默认开启逃逸分析.

开启: -XX:+DoEscapeAnalysis

关闭: -XX:-DoEscapeAnalysis

标量替换

通过逃逸分析确定该对象不会被外部访问,并且对象可以被进一步分解时. jvm不会创建该对象,而是将对象成员变量分解若干个被这个方法使用的成员变量所代替, 这些代替的成员变量在栈帧或者寄存器分配空间, 这样就不会因为没有一大块连续的空间导致对象内存不够分配.

jdk7之后默认开启标量替换

开启: -XX:+EliminateAllocations

关闭: -XX:-EliminateAllocations

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class AllotOnStack {

/**
* java -XX:+PrintGC AllotOnStack
* 关闭栈上分配 -XX:-DoEscapeAnalysis
* ‐Xmx15m ‐Xms15m ‐XX:‐DoEscapeAnalysis ‐XX:+PrintGC ‐XX:+EliminateAllocations
*
*
* 命令 -Xms 启动时堆大小
* -Xmx 最大堆限制
* -XX:+EliminateAllocations 标量替换
* -XX:+DoEscapeAnalysis 栈上分配
* java -Xmx15m -Xms15m -XX:-DoEscapeAnalysis -XX:+PrintGC -XX:+EliminateAllocations AllotOnStack 大量gc
* java -Xmx15m -Xms15m -XX:+DoEscapeAnalysis -XX:+PrintGC -XX:+EliminateAllocations AllotOnStack 无gc
* java -Xmx15m -Xms15m -XX:+DoEscapeAnalysis -XX:+PrintGC -XX:-EliminateAllocations AllotOnStack 大量gc
*
*/
public static void main(String[] args) {
long start = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
alloc();
}

long end = System.currentTimeMillis();
System.out.println(end - start);
}

private static void alloc() {
User user = new User();
user.setId(1);
user.setName("zhuge");
}
}

class User {
private int id;
private String name;

public int getId() {
return this.id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

}

javac AllotOnStack.java 编译

java -Xmx15m -Xms15m -XX:-DoEscapeAnalysis -XX:+PrintGC -XX:+EliminateAllocations AllotOnStack 运行


栈上分配
https://zhaops-hub.github.io/2025/07/25/八股文/对外开放的文档/栈上分配/
作者
赵培胜
发布于
2025年7月25日
许可协议