0%

java | 栈

stack 栈。 JVM statcks 虚拟机栈。

栈就是线程运行时需要的内存空间。

一个栈是由多个栈帧组成的。栈帧是每个方法运行时需要的内存。

  • 栈帧
    • 参数
    • 局部变量
    • 返回地址

每个线程只能有一个活动栈帧,对应着正在执行的那个方法。

垃圾回收是否涉及栈内存

不会,因为,每次方法调用完,栈帧内存都会回收「弹出栈」。

栈内存分配越大越好吗

可以通过设置 VM 参数影响栈内存大小,默认 1024 KB。「Win 特殊一些,受虚拟内存的影响,不一定」

栈内存越大,线程越小。一般使用默认就好了。

方法内的局部变量是否是线程安全的?

这个可以看一下

答案是不一定。

这里再写几个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void m1(){
StringBuilder sb = new StringBuilder();
sb.append(2);
}

public static void m2(StringBuilder sb){
sb.append(2);
}

public static StringBuilder m3(){
StringBuilder sb = new StringBuilder();
sb.append(2);
return sb;
}

其中 m1 是安全的,m2m3 都是不安全的。m3 是因为,把 sb 暴漏出来了,其他线程可以进行修改。

栈内存溢出

有以下情况会导致栈内存溢出

  • 栈帧过多
    • 调用的方法太多了,比如递归
  • 栈帧过大

栈帧过多

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.redisc;

import lombok.extern.slf4j.Slf4j;

@Slf4j(topic = "c.Test")
public class Test {
public static int count;

public static void main(String[] args) throws Exception {
try {
method1();
} catch (Throwable e) {
e.printStackTrace();
System.out.println(count);
}
}

private static void method1() {
count++;
method1();
}

}

输出

1
22178

如果在 VM 中使用 -Xss256k 输出是 2256

栈帧过大

这个通常发生在方法体内,两个变量相互引用,导致,内存溢出。

请我喝杯咖啡吧~