第一次StackOverFlowError
发生时,对 last 的调用doAnything()
被取消,控制从 last 返回到 catch 块doAnything()
。
然而,由于堆栈实际上仍然是满的,调用的简单事实System.out.print("y")
将导致另一个StackOverflowError
原因,因为需要将一些值压入堆栈然后调用函数print()
。
因此,另一个StackOverflowError
再次发生,并且返回现在在前一个的 catch{} 块上返回doAnything()
;另一个StackOverflowError
会发生,因为执行单个调用所需的堆栈空间需要System.out.println("y")
大于从返回调用释放的空间量doAnything()
。
只有当堆栈上有足够的空间来执行调用时System.out.print("y")
,该进程才会停止并且catch 块将成功完成。我们可以通过运行以下代码看到这一点:
public class Principal3b {
static int a = 0;
static int i = 0;
static int j = 0;
public static void main(String[] args) {
System.out.println("X");
doAnything();
System.out.println("Y");
System.out.println(i);
System.out.println(j);
}
private static void doAnything() {
a++;
int b = a;
try {
doAnything();
} catch (final Error e) {
i++;
System.out.println(a);
System.out.println(b);
j++;
}
}
}
请注意,println(a)
使用 a 而不是 a print(a)
; a
因此,如果一切正常,则应在每个值之后打印一个新行。
但是,当我运行它时,我得到以下结果:
X
62066206620662066206620662066206
6190
Y
17
1
这意味着已经有 17 次尝试运行 catch 块。在这些 catch 块执行中,有 9 个在自己生成 StackOverflowError 之前无法打印任何内容;7 能够打印 6190 的值,但在再次出现错误之前无法在其后打印换行符,最后,有一个能够同时打印 6190 的值和其后的换行符;因此最终允许它的 catch 块在没有任何新的 StackOverflowError 的情况下完成并优雅地返回调用堆栈。
当我们处理 StackOverflowError 时,这些数字只是一个示例,不仅在机器之间而且在执行之间会有很大差异,添加或删除任何类型的指令的简单事实也应该改变这些值。但是,这里看到的模式应该保持不变。