Ответ
StackOverflowError — это ошибка времени выполнения (java.lang.VirtualMachineError), которая возникает при переполнении стека вызовов (call stack). Стек вызовов — это область памяти, которая хранит информацию о цепочке вызванных методов (локальные переменные, адреса возврата). Чаще всего это происходит из-за бесконечной или слишком глубокой рекурсии, когда метод вызывает сам себя без достижения базового условия выхода.
Классический пример с бесконечной рекурсией:
public class StackOverflowDemo {
// Рекурсивный метод без условия остановки
public static void infiniteRecursion() {
infiniteRecursion(); // Каждый вызов добавляет новый фрейм в стек
}
public static void main(String[] args) {
infiniteRecursion(); // Приведет к StackOverflowError
}
}
Вывод в консоли:
Exception in thread "main" java.lang.StackOverflowError
at StackOverflowDemo.infiniteRecursion(StackOverflowDemo.java:5)
at StackOverflowDemo.infiniteRecursion(StackOverflowDemo.java:5)
... (тысячи повторяющихся строк)
Более реалистичный пример с ошибкой в условии выхода:
public class Factorial {
// Ошибочная реализация: условие выхода никогда не достигнуто (n всегда > 0)
public static int faultyFactorial(int n) {
if (n > 0) { // Должно быть if (n == 0) return 1;
return n * faultyFactorial(n - 1);
}
// При n = 5, 4, 3, 2, 1, 0, -1, -2... рекурсия уйдет в минус бесконечно.
return 1;
}
public static void main(String[] args) {
// Вызовет StackOverflowError, так как рекурсия никогда не достигнет n <= 0 корректно.
System.out.println(faultyFactorial(5));
}
}
Как избежать StackOverflowError:
- Всегда определять корректное базовое условие в рекурсивных функциях.
- Убедиться, что рекурсия сходится, т.е. каждый шаг приближает к базовому случаю.
- Рассмотреть итеративную альтернативу для очень глубоких вычислений.
- Увеличить размер стека JVM с помощью параметра
-Xss(например,-Xss2m), но это не решение логической ошибки, а временная мера.
Правильная реализация факториала:
public static int correctFactorial(int n) {
if (n == 0 || n == 1) { // Четкое базовое условие
return 1;
}
return n * correctFactorial(n - 1); // Шаг, гарантированно уменьшающий n
}