Яка максимальна глибина стека виклику java?


100

Наскільки глибоко мені потрібно зайти в стек викликів, перш ніж отримати StackOverflowError? Чи залежить платформа відповідей?


1
Тісно пов'язані з : stackoverflow.com/questions/794227 / ...
finnw

Оскільки це гарне запитання, я оновив заголовок на те, що, на мою думку, чіткіше пов'язане зі значенням. (Раніше я думав, що, можливо, ви посилаєтесь на глибину певного стека, який ви захопили, наприклад). Не соромтеся змінити його назад, якщо ви не згодні
Анджей Дойль

Відповіді:


60

Це залежить від кількості віртуальної пам’яті, виділеної на стек.

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

Ви можете налаштувати це за допомогою -Xssпараметра VM або за допомогою Thread(ThreadGroup, Runnable, String, long)конструктора.


13
І, можливо, розмір кадрів стеків, які ви накладаєте на нього?
duffymo

1
Обмеження також залежить від використання стека у функції.
Jarek Przygódzki

1
якщо ми не згадуємо Xss, то?
a3.14_Infinity

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, перш ніж мені набридло.
ary

9
@arya важливою частиною семантики JVM є те, що хвостова рекурсія не підтримується. Це створює масу цікавих проблем для тих, хто хоче реалізувати мови з хвостовою рекурсією на JVM.
Thorbjørn Ravn Andersen

2
public foo() { try { foo(); } finally { foo(); } }може працювати "практично" назавжди, хоча в Java лише.
Феліпе

для мене StackOverflowErrorвідбувається після
8792

2
@ ThorbjørnRavnAndersen оптимізація рекурсії хвоста не підтримується. Швидше за все, у вас може виникнути рецидиви хвоста. Це просто не оптимізує його, щоб не наростити стек викликів.
струнка

19

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

Якщо ви отримаєте переповнення стека, 99% часу це викликано помилкою в коді.


3
+1 для другого абзацу. Про це завжди слід пам’ятати.
mcveat

6
Використовуючи затемнення, я отримую лише 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) {єдиним методом.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.