我到处找都找不到确切的答案。根据文档,Java在以下情况下抛出Java .lang. stackoverflowerror错误:
当由于应用程序递归太深而发生堆栈溢出时引发。
但这引发了两个问题:
除了通过递归,没有其他方法可以导致堆栈溢出吗?
StackOverflowError发生在JVM溢出堆栈之前还是之后?
关于第二个问题:
当Java抛出StackOverflowError时,您是否可以安全地假设堆栈没有写入堆?如果您在抛出堆栈溢出的函数的try/catch中缩小堆栈或堆的大小,您可以继续工作吗?这在任何地方都有记录吗?
我不想要的答案:
发生StackOverflow是由于糟糕的递归。
当堆遇到堆栈时发生StackOverflow。
但这引发了两个问题:
除了通过递归,没有其他方法可以导致堆栈溢出吗?
StackOverflowError发生在JVM溢出堆栈之前还是之后?
当我们分配的大小大于栈的限制时(例如。int x[10000000];)。
第二个答案是
Each thread has its own stack that holds a frame for each method executing on that thread. So the currently executing method is at the top of the stack. A new frame is created and added (pushed) to the top of stack for every method invocation. The frame is removed (popped) when the method returns normally or if an uncaught exception is thrown during the method invocation. The stack is not directly manipulated, except to push and pop frame objects, and therefore the frame objects may be allocated in the Heap and the memory does not need to be contiguous.
因此,通过考虑线程中的堆栈,我们可以得出结论。
堆栈的大小可以是动态的,也可以是固定的。如果线程需要的堆栈大于允许的堆栈,则抛出StackOverflowError。如果一个线程需要一个新的帧,并且没有足够的内存分配它,则抛出OutOfMemoryError。
你可以在这里获得JVM的描述
StackOverFlowError最常见的原因是过度深度递归或无限递归。
例如:
public int yourMethod(){
yourMethod();//infinite recursion
}
在Java中:
内存中有两个区域:堆和堆栈。堆栈内存用于存储局部变量和函数调用,而堆内存用于存储Java中的对象。
如果堆栈中没有剩余内存用于存储函数调用或本地变量,JVM将抛出java.lang.StackOverFlowError
而如果没有更多的堆空间来创建对象,JVM将抛出java.lang.OutOfMemoryError
在c#中,可以通过错误地定义对象属性来实现堆栈溢出。
例如:
private double hours;
public double Hours
{
get { return Hours; }
set { Hours = value; }
}
如你所见,它会一直返回带有大写H的Hours, H本身也会返回Hours,等等。
堆栈溢出也经常发生,因为内存不足,或者当使用托管语言时,因为您的语言管理器(CLR, JRE)将检测到您的代码陷入无限循环。