Was ist die maximale Tiefe des Java-Aufrufstapels?

100

Wie tief muss ich in den Aufrufstapel gehen, bevor ich einen StackOverflowError erhalte? Ist die Antwortplattform abhängig?

ripper234
quelle
Da dies eine gute Frage ist, habe ich den Titel auf etwas aktualisiert, das meiner Meinung nach klarer mit der Bedeutung zusammenhängt. (Früher dachte ich, Sie beziehen sich möglicherweise auf die Tiefe eines bestimmten Stapels, den Sie beispielsweise zur Laufzeit erfasst haben.) Fühlen Sie sich frei, es zurück zu ändern, wenn Sie nicht einverstanden sind.
Andrzej Doyle

Antworten:

60

Dies hängt von der Menge des dem Stapel zugewiesenen virtuellen Speichers ab.

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

Sie können dies mit dem -XssVM-Parameter oder mit dem Thread(ThreadGroup, Runnable, String, long)Konstruktor optimieren .

finnw
quelle
13
Und vielleicht die Größe der Stapelrahmen, die Sie darauf setzen?
Duffymo
1
Das Limit hängt auch von der Stapelverwendung in der Funktion ab.
Jarek Przygódzki
1
Wenn wir das Xss nicht erwähnen, dann?
a3.14_Infinity
31

Ich habe auf meinem System getestet und keinen konstanten Wert gefunden. Manchmal tritt ein Stapelüberlauf nach 8900 Aufrufen auf, manchmal erst nach 7700 Zufallszahlen.

public class MainClass {

    private static long depth=0L;

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

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

}
troy
quelle
15
Ist es nicht so, dass dies rekursiv ist und niemals überlaufen sollte? Edit: Sorry. In Java stürzte es bei 8027 ab; In Scala waren es 8594755, bevor mir langweilig wurde.
Arya
9
@arya Ein wichtiger Teil der JVM-Semantik ist, dass die Schwanzrekursion nicht unterstützt wird. Dies gibt viele interessante Probleme für diejenigen, die Sprachen mit Schwanzrekursion in der JVM implementieren möchten.
Thorbjørn Ravn Andersen
2
public foo() { try { foo(); } finally { foo(); } }kann "praktisch" für immer laufen, allerdings nur in Java.
Felype
für mich StackOverflowErrortritt nach nach 8792
ericdemo07
2
@ ThorbjørnRavnAndersen Die Optimierung der Schwanzrekursion wird nicht unterstützt. Eher offensichtlich kann man eine Schwanzrekursion haben. Es wird einfach nicht optimiert, um den Aufrufstapel nicht zu vergrößern.
schlank
19

Die Stapelgröße kann mit dem -XssBefehlszeilenschalter festgelegt werden. Als Faustregel gilt jedoch, dass sie tief genug ist, Hunderte, wenn nicht Tausende von Aufrufen. (Die Standardeinstellung ist plattformabhängig, auf den meisten Plattformen jedoch mindestens 256 KB.)

Wenn Sie einen Stapelüberlauf erhalten, wird dieser in 99% der Fälle durch einen Fehler im Code verursacht.

biziclop
quelle
3
+1 für zweiten Absatz. Daran sollte man sich immer erinnern.
Mcveat
6
Mit Eclipse erhalte ich nur 1024 rekursive Aufrufe.
Norswap
2
@Norswap Bestimmen Sie das anhand der Größe des Stack-Trace? Dies scheint unabhängig von der tatsächlichen Größe des Stapels auf 1024 begrenzt zu sein.
Brian McCutchon
4

Vergleichen Sie diese beiden Aufrufe:
(1) Statische Methode:

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) Nicht statische Methode unter Verwendung einer anderen Klasse:

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

Die Testrekursionsklasse ist public int testRecursion(int number) {die einzige Methode.

Sechzig Bäume
quelle