什么是StackOverflowError,是什么原因导致的,我应该如何处理它们?


当前回答

如您所说,您需要展示一些代码。: -)

堆栈溢出错误通常发生在函数调用nest太深的时候。请参阅Stack Overflow Code Golf线程,以了解如何发生这种情况(尽管在这个问题的情况下,答案会故意导致堆栈溢出)。

其他回答

在紧急情况下,以下情况将导致堆栈溢出错误。

public class Example3 {

    public static void main(String[] args) {

        main(new String[1]);
    }

}

堆栈溢出通常是由于嵌套函数调用太深(在使用递归时尤其容易,即函数调用自身)或在堆栈上分配大量内存而使用堆更合适。

StackOverflowError之于堆栈,就像OutOfMemoryError之于堆。

无界递归调用会导致堆栈空间被用完。

产生StackOverflowError的示例如下:

class  StackOverflowDemo
{
    public static void unboundedRecursiveCall() {
     unboundedRecursiveCall();
    }

    public static void main(String[] args) 
    {
        unboundedRecursiveCall();
    }
}

如果对递归调用进行了限制,以防止内存中不完整调用的总和(以字节为单位)超过堆栈大小(以字节为单位),则可以避免StackOverflowError。

这个问题的很多答案都是好的。但是,我想采取稍微不同的方法,并对内存的工作原理和(简化的)可视化更好地理解StackOverflow错误给出一些更深入的见解。这种理解不仅适用于Java,而且适用于所有进程。

在现代系统中,所有新进程都有自己的虚拟地址空间(VAS)。从本质上讲,VAS是操作系统在物理内存之上提供的抽象层,目的是确保进程之间不相互干扰内存。内核的任务是将虚拟地址映射到实际的物理地址。


VAS可以分为几个部分:

为了让CPU知道它应该做什么,机器指令必须加载到内存中。这通常被称为代码或文本段,具有静态大小。

在此之上,可以找到数据段和堆。数据段大小固定,包含全局变量或静态变量。 当程序遇到特殊情况时,它可能需要额外分配数据,这就是堆发挥作用的地方,因此它能够动态地增长大小。

堆栈位于虚拟地址空间的另一侧,并使用后进先出(LIFO)数据结构跟踪所有函数调用。与堆类似,程序在运行时可能需要额外的空间来跟踪正在调用的新函数调用。由于堆栈位于VAS的另一侧,它正向相反的方向增长,即朝着堆的方向增长。

博士TL;

这就是StackOverflow错误发挥作用的地方。

由于堆栈向下增长(朝向堆),可能会发生在某个时间点它不能继续增长,因为它会与堆地址空间重叠。一旦发生这种情况,就会发生StackOverflow错误。

发生这种情况最常见的原因是由于程序中的一个错误导致递归调用不能正确终止。


请注意,在某些系统上,VAS的行为可能略有不同,甚至可以分为更多的部分,但是,这种一般理解适用于所有UNIX系统。

StackOverflowError是Java中的运行时错误。

当超过JVM分配的调用堆栈内存量时抛出该异常。

抛出StackOverflowError的一种常见情况是由于过度深度递归或无限递归而导致调用堆栈超出。

例子:

public class Factorial {
    public static int factorial(int n){
        if(n == 1){
            return 1;
        }
        else{
            return n * factorial(n-1);
        }
    }

    public static void main(String[] args){
         System.out.println("Main method started");
        int result = Factorial.factorial(-1);
        System.out.println("Factorial ==>"+result);
        System.out.println("Main method ended");
    }
}

堆栈跟踪:

Main method started
Exception in thread "main" java.lang.StackOverflowError
at com.program.stackoverflow.Factorial.factorial(Factorial.java:9)
at com.program.stackoverflow.Factorial.factorial(Factorial.java:9)
at com.program.stackoverflow.Factorial.factorial(Factorial.java:9)

在上述情况下,可以通过进行编程更改来避免这种情况。 但如果程序逻辑是正确的,它仍然发生,那么你的堆栈大小需要增加。