当栈内存中栈帧过多或者栈帧过大,对于第一个原因,每调用一次方法就会在栈中分配一个栈帧。虽然栈帧用完内存就会自动回收,如果调用的方法之间执行的时间长,就有可能出现,最典型的场景就是方法递归调用。比如我们有个代码:
1 public class Demo { 2 // 记录方法调用次数 3 public static int count = 0; 4 5 public static void main(String[] args) { 6 try { 7 method(); 8 } catch (Throwable e) { 9 e.printStackTrace(); 10 System.out.println(count); 11 } 12 } 13 14 //递归调用,但不设置终止条件 15 private static void method() { 16 count++; 17 method(); 18 } 19 }
栈内存为默认大小1024kb,执行程序出现了栈内存溢出错误。次数为33811次,也就是方法被调用了这么多次栈内存不够了。
这时我们可以通过虚拟机参数 “-Xss” 设置栈内存大小,在idea中设置Configurations,将栈内存设置为256K再次运行程序
这时候循环次数变为2831,因为我们把栈内存调小了。这也是JVM调优栈内存优化的一个简单方法。栈内存太大太小都会出现一定问题。分配过大就会导致同时运行的线程数量减少,太小的话运行的方法调用比较复杂,每次运行时栈帧比较大,栈内存就会内存溢出,所以如何设置要取决于具体的业务场景。