Какова максимальная глубина стека вызовов Java?

102

Насколько глубоко мне нужно углубиться в стек вызовов, чтобы получить StackOverflowError? Зависит ли платформа ответа?

потрошитель234
источник
1
Тесно связано: stackoverflow.com/questions/794227/…
finnw
Поскольку это хороший вопрос, я обновил заголовок до того, что, как мне кажется, более четко связано со значением. (Ранее я думал, что вы, возможно, имеете в виду глубину определенного стека, который вы захватили во время выполнения, например). Если вы не согласны, можете вернуть его обратно.
Анджей Дойл

Ответы:

62

Это зависит от объема виртуальной памяти, выделенной стеку.

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

Вы можете настроить это с помощью -Xssпараметра виртуальной машины или Thread(ThreadGroup, Runnable, String, long)конструктора.

Finnw
источник
14
И, возможно, размер стека, который вы на него кладете?
duffymo
1
Предел также зависит от использования стека в функции.
Ярек Пшигодски
1
если мы не упомянем Xss, тогда?
a3.14_Infinity 04
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
9
@arya важной частью семантики JVM является то, что хвостовая рекурсия не поддерживается. Это создает множество интересных проблем для тех, кто хочет реализовать языки с хвостовой рекурсией на JVM.
Thorbjørn Ravn Andersen
2
public foo() { try { foo(); } finally { foo(); } }может работать «виртуально» вечно, но только в java.
Felype
для меня, StackOverflowErrorпроисходит после 8792
ericdemo07 05
2
Оптимизация хвостовой рекурсии @ ThorbjørnRavnAndersen не поддерживается. Скорее всего, у вас может быть хвостовая рекурсия. Он просто не оптимизирует его, чтобы не увеличивать стек вызовов.
slim
19

Размер стека можно установить с помощью -Xssпереключателя командной строки, но, как правило, он достаточно глубокий, сотни, если не тысячи вызовов. (Значение по умолчанию зависит от платформы, но не менее 256 КБ на большинстве платформ.)

Если вы получаете переполнение стека, в 99% случаев это вызвано ошибкой в ​​коде.

бизиклоп
источник
3
+1 за второй абзац. Об этом нужно всегда помнить.
mcveat
6
Используя eclipse, я получаю только 1024 рекурсивных вызова.
Norswap
2
@Norswap Вы определяете это по размеру трассировки стека? Кажется, что оно ограничено 1024, независимо от фактического размера стека.
Брайан МакКатчон
4

Сравните эти два вызова:
(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) {единственный метод.

шестьдесят деревьев
источник