什么时候发生StackOverflowError?
这个问题在这里已经有了答案:
深度取决于两件事情:
1:堆栈的大小。
2:每次递归中使用的堆栈空间量。
函数参数,局部变量和返回地址都分配在堆栈上,而对象则分配在堆上。
复苏
有可能恢复。
try {
myDeepRecursion();
} catch (StackOverflowError e) {
// We are back from deep recursion. Stack should be ok again.
}
但是,请注意关于错误的以下内容(来自java API doc):
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch.
编辑:
请注意:在递归函数内捕获异常是可以的,但不要尝试捕获错误。 如果堆栈已满,则错误处理将导致新的错误。 简单的事情,例如对System.out.println()
的调用将失败,因为堆栈中没有剩余空间用于返回地址。
这就是为什么错误应该被捕获到递归函数之外的原因。
在JVM抛出StackOverflowError之前递归有多深?
这真的取决于你正在使用的机器,你的JVM及其配置。 (在我当前的设置中,6000 - 8500在后台执行了很多任务),最多也是在应用程序和递归方法中执行的操作。
我们可以恢复一旦StackOverflowError已被抛出?
没有! 我Java抛出一个错误,没有办法恢复正常。 这是异常和错误之间的主要区别。
Error是Throwable的一个子类,表示合理的应用程序不应该尝试捕获的严重问题
阅读更多关于错误的信息
在这里阅读更多关于Java堆栈大小的神话
编辑:
发生错误后仍然可以执行操作,但这样做有意义吗? 你的代码有一个严重的错误! 你不能确定一切正常!
你的代码没有终止,因为你再次调用方法,就像无限循环一样
你可能会看到不同的堆栈深度的原因是堆栈帧不一定是相同的大小。 例如,热点JVM对于JIT编译代码和解释代码具有不同的堆栈帧。 JIT编译器与运行代码并行工作,所以外部因素(如机器上的负载)可能会影响JVM何时/如果JIT堆栈帧开始使用。
你应该记住的一件事是,当你得到一个StackOverflowError
,几乎你所做的任何事情都可能导致另一个StackOverflowError
。 例如,在catch
部分中打印错误类的名称也可能会耗尽堆栈空间,因此另一个StackOverflowError
将被抛出堆栈。
有些人声称,由于JVM正在关闭,您无法从Error
恢复。 这是不正确的; 你可以从一些错误中恢复。 有关StackOverflowError
和OutOfMemoryError
的棘手问题是,一旦你捕获了一个,你就完全不能保证程序的状态; 例如,您使用的关键数据结构可能处于不一致的状态。 这使得恢复很难或不可能。