À quelle profondeur dois-je aller dans la pile d'appels avant d'obtenir une StackOverflowError ? La réponse dépend-elle de la plateforme ?
Réponses
Trop de publicités?Cela dépend de la quantité de mémoire virtuelle allouée à la pile.
http://www.odi.ch/weblog/posting.php?posting=411
Vous pouvez ajuster cela avec le paramètre VM -Xss
ou avec le constructeur [Thread(ThreadGroup, Runnable, String, long)](http://download.oracle.com/javase/6/docs/api/java/lang/Thread.html#Thread%28java.lang.ThreadGroup,%20java.lang.Runnable,%20java.lang.String,%20long%29)
.
J'ai testé sur mon système et n'ai trouvé aucune valeur constante, parfois le dépassement 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();
}
}
La taille de la pile peut être définie avec l'interrupteur de ligne de commande -Xss
, mais en règle générale, elle est suffisamment profonde, avec des centaines, voire des milliers d'appels en profondeur. (La valeur par défaut dépend de la plate-forme, mais est d'au moins 256k sur la plupart des plates-formes.)
Si vous obtenez un dépassement de pile, 99% du temps, cela est causé par une erreur dans le code.
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 autre classe :
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écursion de test a public int testRecursion(int number) {
comme seul méthode.
En parcourant un arbre avec une profondeur énorme, nous pourrions être confrontés à ceci
/**
* -Xss10M
* nombre maximum d'appels de pile 92766
* -Xss100M
* nombre maximum d'appels de pile 2148286
*/
public class MaxCallStack {
private Integer stackCount = 0;
public static void main(String[] args) {
MaxCallStack maxStack = new MaxCallStack();
maxStack.evaluate();
}
private void evaluate() {
try {
Tree tree = new Tree();
tree.left = tree;
traverse(tree);
} catch (StackOverflowError e) {
System.out.println(String.format("nombre maximum d'appels de pile %s", stackCount));
}
}
private void traverse(Tree tree) {
stackCount++;
if (tree.left != null) {
traverse(tree.left);
}
if (tree.right != null) {
traverse(tree.right);
}
}
private class Tree {
Tree left;
Tree right;
}
}