Qual é a profundidade máxima da pilha de chamadas java?

100

Quão profundo eu preciso ir na pilha de chamadas antes de obter um StackOverflowError? A resposta da plataforma depende?

ripper234
fonte
1
Intimamente relacionado: stackoverflow.com/questions/794227/…
finnw
Como essa é uma boa pergunta, atualizei o título para algo que sinto que está mais claramente associado ao significado. (Anteriormente, pensei que você poderia estar se referindo à profundidade de uma pilha específica que você capturou em tempo de execução, por exemplo). Sinta-se à vontade para alterá-lo novamente se você discordar.
Andrzej Doyle

Respostas:

31

Eu testei em meu sistema e não encontrei nenhum valor constante, às vezes o estouro da pilha ocorre após 8.900 chamadas, às vezes somente após 7700, números aleatórios.

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
fonte
15
Não é o caso que esta cauda é recursiva e nunca deve transbordar? Edit: Desculpe. Em Java, ele travou em 8027; no Scala, chegava a 8594755 antes de eu ficar entediado.
arya de
9
@arya, uma parte importante da semântica da JVM é que a recursão final não é suportada. Isso oferece muitos problemas interessantes para aqueles que desejam implementar linguagens com recursão de cauda na JVM.
Thorbjørn Ravn Andersen
2
public foo() { try { foo(); } finally { foo(); } }pode ser executado "virtualmente" para sempre, embora apenas em java.
Felype
para mim, StackOverflowErrorocorre depois de 8792
ericdemo07
2
@ ThorbjørnRavnAndersen A otimização da recursão da cauda não é suportada. Obviamente, você pode ter recursão de cauda. Ele simplesmente não o otimiza para não aumentar a pilha de chamadas.
slim
19

O tamanho da pilha pode ser definido com a -Xssopção de linha de comando, mas, como regra geral, é profundo o suficiente, centenas, senão milhares de chamadas. (O padrão depende da plataforma, mas pelo menos 256k na maioria das plataformas.)

Se você obtiver um estouro de pilha, 99% das vezes é causado por um erro no código.

biziclop
fonte
3
1 para o segundo parágrafo. Deve-se sempre lembrar disso.
mcveat
6
Usando o eclipse, recebo apenas 1024 chamadas recursivas.
Norswap
2
@Norswap Você está determinando isso pelo tamanho do rastreamento de pilha? Isso parece estar limitado a 1024, independentemente do tamanho real da pilha.
Brian McCutchon de
4

Compare essas duas chamadas:
(1) Método estático:

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étodo não estático usando uma classe diferente:

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

A classe de recursão de teste tem public int testRecursion(int number) {como único método.

sessenta árvores
fonte