Java呼び出しスタックの最大深度はいくつですか?


100

StackOverflowErrorを取得する前に、コールスタックにどのくらい深く入る必要がありますか?回答プラットフォームは依存していますか?



これは良い質問なので、タイトルを意味に関連していると感じられるものに更新しました。(以前は、たとえば、実行時にキャプチャした特定のスタックの深さを参照している可能性があると思っていました)。同意しない場合は、自由に元に戻してください。
Andrzej Doyle

回答:


60

スタックに割り当てられている仮想メモリの量によって異なります。

http://www.odi.ch/weblog/posting.php?posting=411

これは、-XssVMパラメーターまたはThread(ThreadGroup, Runnable, String, long)コンストラクターを使用して調整できます。


13
そして、おそらくあなたがそれに入れているスタックフレームのサイズは?
duffymo 2011年

1
この制限は、関数でのスタックの使用状況にも依存します。
JarekPrzygódzki2013年

1
Xssについて触れない場合は、
a3.14_Infinity 2016

31

システムでテストしましたが、定数値が見つかりませんでした。スタックオーバーフローが発生するのは、8900回の呼び出しの後、7700回の乱数の後だけです。

public class MainClass {

    private static long depth=0L;

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

    private static void deep(){
        System.err.println(++depth);
        deep();
    }

}

15
これは末尾再帰であり、オーバーフローしてはならないのではないですか?編集:すみません。Javaでは8027でクラッシュしました。Scalaでは、退屈する前に8594755に達しました。
arya 2015

9
@aryaは、JVMセマンティクスの重要な部分であり、末尾再帰はサポートされていません。これは、JVMで末尾再帰を使用して言語を実装したい人に多くの興味深い問題を与えます。
するThorbjörnRavnアンデルセン

2
public foo() { try { foo(); } finally { foo(); } }ただし、Javaでのみ、「仮想的に」永久に実行できます。
Felype 2015年

私にとっては、StackOverflowError8792以降に発生します
ericdemo07

2
@ThorbjørnRavnAndersen末尾再帰の最適化はサポートされていません。むしろ、明らかに末尾再帰が可能です。呼び出しスタックを拡張しないように最適化することはありません。
スリム

19

スタックサイズは-Xssコマンドラインスイッチで設定できますが、経験則として、それは十分な深さであり、数千の呼び出しではなくても数百の呼び出しの深さです。(デフォルトはプラットフォームに依存しますが、ほとんどのプラットフォームでは256k以上です。)

スタックオーバーフローが発生した場合、99%はコードのエラーが原因です。


3
2番目の段落の+1。これについては常に覚えておく必要があります。
mcveat 2011年

6
Eclipseを使用すると、1024回の再帰呼び出ししか受け取れません。
Norswap 2013年

2
@Norswapスタックトレースのサイズによってそれを決定していますか?スタックの実際のサイズに関係なく、1024に制限されているようです。
ブライアンマッカッション2017

4

次の2つの呼び出しを比較してください:
(1)静的メソッド:

public static void main(String[] args) {
    int i = 14400; 
    while(true){   
        int myResult = testRecursion(i);
        System.out.println(myResult);
        i++;
    }
}

public static int testRecursion(int number) {
    if (number == 1) {
        return 1;
    } else {
        int result = 1 + testRecursion(number - 1);
        return result;
    }    
}
 //Exception in thread "main" java.lang.StackOverflowError after 62844

(2)別のクラスを使用する非静的メソッド:

public static void main(String[] args) {
    int i = 14400;
    while(true){       
        TestRecursion tr = new TestRecursion ();
        int myResult = tr.testRecursion(i);
        System.out.println(myResult);
        i++;
    }
} 
//Exception in thread "main" java.lang.StackOverflowError after 14002

テスト再帰クラスはpublic int testRecursion(int number) {唯一のメソッドとして持っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.