Quelle est la profondeur maximale de la pile d'appels Java?

100

De quelle profondeur ai-je besoin pour accéder à la pile d'appels avant d'obtenir une StackOverflowError? La plate-forme de réponse dépend-elle?

ripper234
la source
1
Étroitement lié: stackoverflow.com/questions/794227/…
finnw
Comme c'est une bonne question, j'ai mis à jour le titre pour quelque chose qui me semble plus clairement associé à la signification. (Auparavant, je pensais que vous pourriez faire référence à la profondeur d'une pile particulière que vous aviez capturée au moment de l'exécution, par exemple). N'hésitez pas à le modifier si vous n'êtes pas d'accord.
Andrzej Doyle

Réponses:

31

J'ai testé sur mon système et je n'ai trouvé aucune valeur constante, parfois un débordement de pile se produit après 8900 appels, parfois seulement après 7700, des nombres aléatoires.

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
la source
15
N'est-il pas vrai que c'est la queue récursive et ne devrait jamais déborder? Edit: Désolé. En Java, il s'est écrasé à 8027; à Scala, il est monté à 8594755 avant de m'ennuyer.
arya
9
@arya une partie importante de la sémantique JVM est que la récursivité de queue n'est pas prise en charge. Cela pose beaucoup de problèmes intéressants pour ceux qui veulent implémenter des langages avec une récursion de queue sur la JVM.
Thorbjørn Ravn Andersen
2
public foo() { try { foo(); } finally { foo(); } }peut fonctionner «virtuellement» pour toujours, en Java uniquement.
Felype
pour moi, StackOverflowErrorse produit après 8792
ericdemo07
2
@ L' optimisation de la récursivité de la queue ThorbjørnRavnAndersen n'est pas prise en charge. De toute évidence, vous pouvez avoir une récursivité de queue. Cela ne l'optimise tout simplement pas pour ne pas augmenter la pile d'appels.
slim
19

La taille de la pile peut être définie avec le -Xsscommutateur de ligne de commande, mais en règle générale, elle est suffisamment profonde, des centaines, voire des milliers d'appels. (La valeur par défaut dépend de la plate-forme, mais au moins 256 Ko dans la plupart des plates-formes.)

Si vous obtenez un débordement de pile, 99% du temps, il est causé par une erreur dans le code.

biziclop
la source
3
+1 pour le deuxième paragraphe. Il faut toujours s'en souvenir.
mcveat
6
En utilisant eclipse, je ne reçois que 1024 appels récursifs.
Norswap
2
@Norswap Déterminez-vous cela par la taille de la trace de pile? Cela semble être limité à 1024 quelle que soit la taille réelle de la pile.
Brian McCutchon
4

Comparez ces deux appels:
(1) Méthode statique:

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) Méthode non statique utilisant une classe différente:

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

La classe de récursivité de test a public int testRecursion(int number) {comme seule méthode.

soixante arbres
la source