4
public class Foo {

    public static void main(String[] args) {
        foo();
    }

    public static void foo() {
        try {
            System.out.println("try");
            foo();
        } catch (Throwable e) {
            System.out.println("catch");
            foo();
        } finally {
                System.out.println("finally");
                foo();
        }
    }
}

このコードの出力を誰が説明できますか?

1.Eclipse(エンドレス)クライアントモードでの出力:

    試す
    試す
    ....


    ...
    ...
    最後に最後に試してみてください
    最後に最後に試してみてください
    試す
    試す
    試す
    最後に最後に試してみてください
    最後に最後に試してみてください
    試す
    最後に最後に試してみてください
    最後に最後に試してみてください
    試す
    ....
    ....

2. Linux (クラッシュ) サーバーモードでの出力:

    試す
    試す
    ...

    ...
    試す
    試す
    試す
    試す
    試す
    試す
    pc 0x00002aaaab1c53f0 およびハンドラ bci -1 の例外ハンドラがありません
       例外:

     コンパイルされた例外テーブル:
    ExceptionHandlerTable (サイズ = 3304 バイト)
    catch_pco = 700 (1 エントリ)
      スコープの深さ 0 で bci -1 -> pco 11039
    catch_pco = 1736 (1 エントリ)
      スコープの深さ 0 で bci -1 -> pco 11473
    catch_pco = 1756 (1 エントリ)
      スコープの深さ 0 で bci -1 -> pco 11433
    catch_pco = 1776 (1 エントリ)

4

1 に答える 1

8

「Java Puzzlers」という本でこれを覚えていると思います。try ブロックは無制限の再帰を実行し、すぐに StackOverflowError がスローされます。try ブロックと catch ブロックは再帰を再開しますが、それに応じて残りのスタックが少なくなります。ただし、再帰呼び出しが返されるたびに、残りのスタックが再び大きくなります...

最終結果は、スタックのサイズに応じた深さを持つツリーを形成するコール グラフです。主流の JVM のデフォルトのスタック サイズでは、ツリーが非常に大きくなり、ツリーが完全に走査されてプログラムが終了するまで、十億年も待たなければなりません。

編集:クライアント モードで表示されているのは、コール グラフのトラバーサルです。サーバー モードの Linux で見られるのは、JVM のバグまたはハードウェアの欠陥です (RAM の障害がこの影響を与える可能性があります)。

于 2011-07-19T09:19:17.067 に答える