一、异常场景
StackOverflowError:在栈深度大于可用的栈深度时,会抛出此异常,在虚拟机设置中-Xss参数是用来设置栈大小的,该问题常见于递归中,一旦递归深度过高或者函数中局部变量过多,则有可能会出现此问题
二、影响因素
- 局部变量
public static void testStackOverFlow(long a,long b,long c){
long d=0,e=0,f=0;//占用栈空间
testStackOverFlow(a,b,c);//相同栈大小情况下 调用次数会减少
}
public static void testStackOverFlow(){
testStackOverFlow();
}
总结:对于一个函数,它的参数越多,内部局部变量越大,它的栈帧就越大,其嵌套调用次数就越少
优化方法:递归:局部变量中的子空间是可以重用的,因为局部变量的作用方位可以不在整个方法体中例如:
public static void testStatck1(){
{
byte[] a=new byte[1024*1024];
//在方法体没运行结束前 a会一直不被释放
}
}
public static void test(){
testStatck1();
//总是可以回收testStatck1中的 a,因为上层函数testStatck1的栈帧已经被销毁,则栈帧中的局部变量表也会被销毁,a自然会被回收
}
public static void testStatck(){
{
byte[] a=new byte[1024*1024];
//此处注意如果作用于方法体中的变量少于此块中的局部变量 需要手动释放内存,例如方法体中没有b变量,则要设置a=null,将a的局部变量表销毁;
//局部变量中的字会影响GC回收,如果这个字没有被后续代码复用,那么它引用的对象不会被GC释放
//a=null;
}
long b=0;//b会复用a的子空间
}
- -Xss :调大Xss参数