我到处找都找不到确切的答案。根据文档,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的描述
在c#中,可以通过错误地定义对象属性来实现堆栈溢出。
例如:
private double hours;
public double Hours
{
get { return Hours; }
set { Hours = value; }
}
如你所见,它会一直返回带有大写H的Hours, H本身也会返回Hours,等等。
堆栈溢出也经常发生,因为内存不足,或者当使用托管语言时,因为您的语言管理器(CLR, JRE)将检测到您的代码陷入无限循环。