引言: 在JVM中除了堆heap之外,还有stack栈;栈速度快,空间小,主要用于存放方法级别的临时数据,本文将分析其使用以及注意事项。
1. 栈的应用场景
栈主要用以存储方法调用之时,方法体之内的临时变量; 在单个线程调用和执行过程中,系统也会为thread分配独立的栈空间;在程序执行过程中,不同的类之间的方法调用,其调用层次,也会被存放到栈之中,所以栈的大小决定了方法调用的深度;最常见的情况是自我迭代的时候,栈溢出的情况。
2. 栈的设置
参数设置: -Xss128k 后面是数字+单位
使用说明: 设置栈的大小
代码示例:
public class TestStackDeep {
private static int count = 0;
public static void recursion(long a, long b, long c) {
long e = 1, f = 2, g = 3, h = 4, i = 5, k = 6, q = 7, x = 8, y = 9, z = 10;
count++;
recursion(a, b, c);
}
public static void main(String args[]) {
try {
recursion(0L, 0L, 0L);
} catch (Throwable e) {
System.out.println("deep of calling = " + count);
e.printStackTrace();
}
}
}
代码本身进行了深度的自我调用,直至stack溢出。
运行结果:
deep of calling = 301
java.lang.StackOverflowError
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:7)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
调用次数301, StackOverflowError.
代码示例2:
JVM参数设置: -Xss256k
运行结果:
deep of calling = 754
java.lang.StackOverflowError
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:7)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
at org.homework.test.jvm.jvmopt.TestStackDeep.recursion(TestStackDeep.java:9)
运行结果分析:
迭代调用次数754, 随着stack空间的大小,迭代次数变大。
3. 注意事项
Stack本身空间小,所以在设置过程中,受限于其空间,不要设置太大。 如果想增加迭代次数,则可以进行如下操作:
- 尽可能使用占用空间小的数据类型,比如int替代long, float替代double等
- 尽可能减少局部变量的使用
- 增大-Xss的大小
- 避免使用逃逸分析,-XX:-DoEscapeAnalysis. 详细内容可以参考我的blog关于逃逸分析的内容。