当前位置: 首页 > 面试题库 >

为什么可以从StackOverflowError中恢复?

荀俊迈
2023-03-14
问题内容

我很惊讶即使StackOverflowError在Java中发生故障后仍可以继续执行。

我知道那StackOverflowError是Error类的一个子集。错误类Error被贬义为“
Throwable的子类,它指示合理的应用程序不应尝试捕获的严重问题”。

这听起来像是一条建议,而不是一条规则,这表明实际上允许捕获像StackOverflowError这样的错误,这取决于程序员的合理性。看到了,我测试了这段代码,它正常终止。

public class Test
{
    public static void main(String[] args)
    {
        try {
            foo();
        } catch (StackOverflowError e) {
            bar();
        }
        System.out.println("normal termination");
    }

    private static void foo() {
        System.out.println("foo");
        foo();
    }

    private static void bar() {
        System.out.println("bar");
    }
}

怎么会这样?我认为,当引发StackOverflowError时,堆栈应该已满,以至于没有空间可以调用另一个函数。错误处理块是在其他堆栈中运行还是在这里发生了什么?


问题答案:

当堆栈溢出并被StackOverflowError抛出时,通常的异常处理将展开堆栈。展开堆栈意味着:

  • 中止当前活动功能的执行
  • 删除其堆栈帧,继续执行调用函数
  • 中止调用者的执行
  • 删除其堆栈帧,继续执行调用函数
  • 等等…

…直到发现异常。这是正常的(实际上是必要的),并且与引发哪个异常以及原因无关。由于您是在第一次调用之外捕获到异常的foo(),因此foo已清除了填充堆栈的数千个堆栈帧,并且大部分堆栈可以自由使用。



 类似资料:
  • 令我惊讶的是,即使在Java中发生了StackOverflowerError之后,仍然可以继续执行。 我知道StackOverflowerError是类错误的子类。类错误被描述为“Throwable的一个子类,表示合理的应用程序不应试图捕捉的严重问题。” 这听起来更像是一个建议而不是规则,补充说捕获像StackOverflow Error这样的错误实际上是允许的,这取决于程序员不这样做的合理性。看

  • 问题内容: public class Category { 在正在生成。 问题答案: 当您执行时,您称呼孩子们的。这里没有问题,只不过您在这里调用了父对象。这将称呼孩子,等等。 不错的无限循环。 摆脱它的最好方法是将您的方法更改为: 这样,您将不打印parentCategory,而仅显示其名称,不显示无限循环,不显示StackOverflowError。 编辑: 正如博洛在下面说的那样,您将需要检

  • 顺着我之前的一个问题,大部分评论都说“就是不要,你处于冷宫状态,你要杀光一切,重新开始”。还有一个“安全”的变通方法。 我不明白的是为什么分割错误本质上是不可恢复的。 写入受保护内存的时刻被捕获-否则,不会发送。 如果能够捕捉到写入受保护内存的时刻,我不明白为什么——理论上——它不能在某个低级别上恢复,并将SIGSEGV转换为标准软件异常。 请解释为什么在出现分段错误后,程序处于不确定状态,因为很

  • 这是我的父类,有两个名为的方法。带有参数的那个在子类中使用。 这是我的子类,在子类的方法中,我使用父类的方法: 当我尝试显示子类的对象时,我得到以下错误: 线程“main”java.lang.StackOverflowError中出现异常

  • 版本flink 1.7 我正在尝试从保存点(或检查点)还原flink作业,该作业所做的是读取kafka的内容- 我使用rocksdb和启用的检查点。 现在我尝试手动触发一个保存点。每个聚合的预期值为30(1个数据/每分钟)。但是当我从保存点(flink run-d-s{url})恢复时,聚合值不是30(小于30,取决于我取消flink作业和恢复的时间)。当作业正常运行时,它得到30。 我不知道为什

  • 问题内容: StackOverflowError和OutOfMemoryError有什么区别,以及如何在应用程序中避免它们? 问题答案: 简短答案: 与堆有关。 与堆栈有关 长答案: 当您开始时,定义它可以使用多少RAM进行处理。出于处理目的将其划分为某些内存位置,其中两个是 & 如果内存中有大对象(或被引用的对象),则会看到。如果您对对象有很强的引用,则GC无法清理为该对象分配的内存空间。当JV