← Назад к вопросам

Какое исключение возникает, если заканчивается память в стеке?

2.2 Middle🔥 121 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

StackOverflowError в Java

StackOverflowError — это исключение, которое возникает, когда заканчивается место в стеке вызовов (call stack) JVM. Это Error, а не Exception, что означает, что его обычно нельзя обработать и приложение должно завершиться.

Природа исключения

В Java есть два типа памяти:

  • Heap — для объектов (контролируется GC)
  • Stack — для локальных переменных и вызовов методов (строго ограничен размер)

Каждый вызов метода создаёт новый stack frame с локальными переменными. Если вызовов накопится слишком много, стек переполнится и возникнет StackOverflowError.

Основные причины

1. Бесконечная рекурсия (самая частая)

public class RecursionExample {
    public static void infiniteRecursion(int n) {
        System.out.println(n);
        infiniteRecursion(n + 1); // Никогда не останавливается!
    }
    
    public static void main(String[] args) {
        infiniteRecursion(0); // StackOverflowError
    }
}

Выход: Exception in thread "main" java.lang.StackOverflowError

2. Косвенная рекурсия

public class IndirectRecursion {
    public void methodA() {
        methodB();
    }
    
    public void methodB() {
        methodA(); // A вызывает B, B вызывает A — бесконечно
    }
}

3. Очень глубокая рекурсия (превышение лимита стека)

public class DeepRecursion {
    public static long factorial(int n) {
        if (n <= 1) return 1;
        return n * factorial(n - 1); // Со временем переполнится
    }
    
    public static void main(String[] args) {
        factorial(10000); // StackOverflowError
    }
}

Разница: Error vs Exception

ХарактеристикаErrorException
НаследуетThrowableThrowable
ОбработкаНе следует ловитьДолжна быть обработана
ПричинаСистемные проблемы (память, стек)Ошибки приложения
ПримерStackOverflowError, OutOfMemoryErrorNullPointerException, IOException
// ❌ Плохо — пытаться ловить StackOverflowError
try {
    infiniteRecursion(0);
} catch (StackOverflowError e) {
    System.out.println("Ошибка!"); // Не сработает, стек уже завален
}

// ✅ Правильно — предотвратить рекурсию
if (n > maxDepth) {
    throw new IllegalArgumentException("Слишком глубокая рекурсия");
}

Как избежать

1. Всегда добавляй базовый случай

public static long factorial(int n) {
    if (n <= 1) return 1; // ← Base case!
    return n * factorial(n - 1);
}

2. Используй итерацию вместо рекурсии

// Рекурсия (рискованно для больших n)
public static int sumRecursive(int[] arr, int index) {
    if (index == arr.length) return 0;
    return arr[index] + sumRecursive(arr, index + 1);
}

// Итерация (безопасно)
public static int sumIterative(int[] arr) {
    int sum = 0;
    for (int num : arr) {
        sum += num;
    }
    return sum;
}

3. Увеличь размер стека (если нужно)

# При запуске JVM
java -Xss4m MyApplication # 4 MB для стека вместо дефолтного 1MB

4. Используй структуры данных для замены рекурсии

// Вместо рекурсии - стек или очередь
public class TreeTraversal {
    public void depthFirstSearch(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            System.out.println(node.value);
            
            if (node.right != null) stack.push(node.right);
            if (node.left != null) stack.push(node.left);
        }
    }
}

Отладка

Если StackOverflowError возникает в продакшене:

  1. Включи full stack trace: jvm -XX:+PrintStackTraceOnException
  2. Найди метод, который вызывает сам себя (look for repeating method names)
  3. Добавь условие выхода или замени рекурсию итерацией
  4. Увеличь -Xss если это авторитетный случай (например, deep tree parsing)

Итого

StackOverflowError возникает при переполнении стека вызовов, обычно из-за неконтролируемой рекурсии. Это Error, который нельзя обработать, поэтому проактивное предотвращение (базовые случаи, итерация вместо рекурсии) — ключ к надёжному коду.

Какое исключение возникает, если заканчивается память в стеке? | PrepBro