java如何处理StackOverflowError?

时间:2018-06-07 16:04:10

标签: java stack-overflow

这是我的示例应用

public class Main {

    private long[] exceptionLevels = new long[1000];
    private int index;

    public static void main(String... args) {
        Main main = new Main();
        try {
            main.foo(0);
        } finally {
            Arrays.stream(main.exceptionLevels)
                    .filter(x -> x != 0)
                    .forEach(System.out::println);
        }
    }

    private void foo(int level) {
        try {
            foo(level + 1);
        } catch (StackOverflowError e) {
            exceptionLevels[index++] = level;
            bar(level + 1);
        }
    }

    private void bar(int level) {
        try {
            bar(level + 1);
        } catch (StackOverflowError e) {
            exceptionLevels[index++] = -level;
        }
    }
}

有时候,当我运行应用程序时,我会看到像这样的结果

8074
8073
-8074

这实际上意味着发生以下事件

  • foo(8073)调用foo(8074)
  • foo(8074)调用foo(8075)死掉
  • foo(8074)记录自己并调用bar(8075)死掉
  • foo(8074)死了,foo(8073)捕获它,记录自己并调用bar(8074)
  • bar(8074)调用bar(8075)死亡,因此bar(8074)自行记录
  • 从所有方法返回,优雅地关闭

我明白了,一切都很好。因此,获得

是一种可以理解的模式
X, X-1, -X

对于调用X

的某些最高级别

但有时,调用Main会产生这种输出

6962
6961
-6963

实际上是

X, X-1, -(X+1)

所以问题是,如何?

P.S。此外,当我将所有内容更改为静态时,程序会完全改变它的行为,所以即使有时我得到的结果也超过3个。

编辑:当我使用-Xss228k运行时,我总是得到

1281
1280
-1281

但是再次使用-Xss1m运行会让我看到随机堆栈大小,有时会出现上述情况。

1 个答案:

答案 0 :(得分:2)

运行代码可能会导致其他可能的输出。在我的PC(Java 8,Windows)上,我主要得到一对像:

这样的值
7053
-7055

但在极少数情况下我得到:

9667
9666
-9667

不建议捕获任何java.lang.Error,这是JVM可能无法恢复的异常情况。