在说栈溢出这个话题之前,我们先来认识一下什么是栈。栈在内存当中是一个特殊的存储区域,它遵循着"先进后出"的原则。在程序运行时,栈主要用于存储函数的局部变量、参数以及函数的返回(return)地址等信息。当我们的程序调用一个函数时,就会在栈中创建该方法对应的栈帧,当函数运行结束时,这个栈帧就会被"弹出"栈。

image-20250923210955533.png

栈溢出,就是往这个栈里面放的东西太多,超出它的承载能力,导致栈无法正常工作。

下面我们来说几个栈溢出的常见原因

  1. 方法递归调用,深度过大

    平时业务开发中递归调用方法是很常见的,但是如果使用不当,就有可能出现栈溢出的情况。下面写个简单的示例代码:

    public class StackOverflow {
        static int i = 0;
        public static void main(String[] args) {
            stackOverflow();
        }
        public static void stackOverflow(){
    		System.out.println("输出一句话,方便观察程序运行情况:"+i++);
            stackOverflow();
        }
    }
    

    上面是一个没有退出条件的递归,这里只是为了测试效果才这么写。每一次递归,都会在栈中分配新的内存空间来存储局部变量和方法返回地址等信息。栈的空间是有限的,当递归深度超过了栈的容量,栈溢出就会发生。

  2. 方法中有大量的局部变量

    在方法内部声明太多的局部变量,也可能导致栈溢出。当方法被调用时,这些局部变量都需要在栈上分配内存空间。示例代码如下:

    public class StackOverflow {
        static int i = 0;
        public static void main(String[] args) {
            stackOverflow();
        }
        public static void stackOverflow(){
            long i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,i20,i21,i22,i23,i24,i25,i26,i27,i28,i29,i30;
            System.out.println("输出一句话,方便观察程序运行情况:"+i++);
            stackOverflow();
        }
    }
    

    栈溢出的表现

image-20250923220731779.png

栈溢出时,程序会抛出java.lang.StackOverflowError异常。

解决栈溢出的方法

1.栈是线程私有的,我们可以通过调整jvm参数来解决栈溢出的问题。jvm提供了-Xss参数来设置每个线程的栈大小。例如:

java -Xss4m XXX.jar

这里将栈的大小设置到了4M。但是我们也要注意,栈空间占用的内存空间多了,那么堆内存空间就减小了,所以需要合理设置。

2.减少局部变量数量:在方法中定义必要的局部变量,避免过多占用栈空间。

3.优化方法调用链:尽量缩短方法调用链,减少栈空间占用。

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]