1. ホーム

[解決済み】 Try-finallyブロックがStackOverflowErrorを防ぐ

2022-03-25 06:55:05

質問

次の2つの方法について見てみましょう。

public static void foo() {
    try {
        foo();
    } finally {
        foo();
    }
}

public static void bar() {
    bar();
}


実行中 bar() は明らかに StackOverflowError が、実行すると foo() は実行されません (プログラムが無限に実行されるように見えるだけです)。 なぜでしょうか?

解決方法は?

永遠に実行されるわけではありません。スタックオーバーフローのたびに、コードはfinallyブロックに移動します。問題は、本当に、本当に長い時間がかかるということです。時間のオーダーは O(2^N) で、ここで N は最大スタック深さである。

最大深度が5であると仮定すると

foo() calls
    foo() calls
       foo() calls
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
       finally
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
    finally calls
       foo() calls
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
       finally
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
finally calls
    foo() calls
       foo() calls
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
       finally
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
    finally calls
       foo() calls
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
       finally
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()

各レベルを最終ブロックに組み込むには、2倍の時間がかかり、スタックの深さは 万個以上。1秒間に10,000,000回呼び出すとすると、10^3003秒、つまり宇宙の年齢よりも長い時間がかかることになります。