Исключения

Исключения #

1. Расскажите про иерархию исключений #

Exceptions

Interface Throwable - общий предок для всех исключений


2. Что такое Error и Exception? #

Error - Связаны с проблемами уровня JVM

Exception - Являются результатом проблем в программе


3. Расскажите про обрабатываемые и необрабатываемые исключения #

Checked - Exception. Должны обрабатываться блоком catch, или описываться в сигнатуре метода (IOException)

Unchecked - Ошибки Error, а так же исключения времени выполнения (RuntimeException) и его наследниками. Могут не обрабатываться блоком catch и не быть описаны в сигнатуре метода


4. О чем говорит ключевое слово throws? #

Метод потенциально может выбросить исключение с указанным типом (элемент контракта метода). Передаёт обработку исключения вышестоящему методу.


5. Как создать собственное («пользовательское») исключение? #

Необходимо унаследоваться от базового класса требуемого типа исключений (например, от Exception или RuntimeException) и переопределить методы.


6. Расскажите про механизм обработки исключений в java (Try-catch-finally) #

  • Try - блок в котором может возникнуть исключение
  • Catch - блок в котором мы ловим исключение и пишем логику его обработки
  • Finally - блок, который обязательно отработает

7. Возможно ли использование блока try-finally (без catch)? #

Да, в таком случае после try выполнится finally


8. Может ли один блок catch отлавливать сразу несколько исключений? #

Да


9. Всегда ли выполняется блок finally? Существуют ли ситуации, когда блок finally не будет выполнен? #

Да, кроме случаев завершения программы или JVM. Finally может не выполниться в случае если в блоке try вызывает System.exit(0)


10. В каком порядке следует обрабатывать исключения в catch блоках? #

От наследника к родителю. Иначе мы не дойдем до наследника


11. Что такое механизм try-with-resources? #

Это механизм, который автоматически закрывает ресурс. В качестве ресурса можно использовать любой объект, класс которого реализует интерфейс AutoClosable или Closable (Scanner, например)


12. Ошибка OutOfMemoryError. Поймать утечку памяти и пофиксить #

Ошибка OutOfMemoryError возникает, когда JVM не может выделить достаточно памяти для выполнения программы. Это может быть связано с утечками памяти, неправильной конфигурацией или большим объемом данных. Вот пошаговый процесс, как выявить и устранить причину:

  1. Соберите дамп памяти.
  2. Найдите источники утечки.
  3. Исправьте типичные проблемы:
    • Неосвобожденные ресурсы.
    • Переполненные коллекции.
    • Статические ссылки.
    • Неотписавшиеся слушатели.
  4. Убедитесь, что память используется корректно.

13. @SneakyThrows в Lombok #

@SneakyThrows — это аннотация Lombok, которая позволяет автоматически обрабатывать исключения, не требуя явного указания try-catch или объявления throws в методе. Lombok оборачивает вызов в блок, который выбрасывает исключение как RuntimeException.

@SneakyThrows
public void riskyMethod() {
    throw new IOException("Exception example"); // Не нужно объявлять throws IOException
}

14. StackOverflowError vs OutOfMemoryError #

Оба исключения (StackOverflowError и OutOfMemoryError) относятся к ошибкам времени выполнения (Error), которые указывают на критические проблемы, связанные с памятью в JVM. Однако у них разные причины и способы возникновения.

StackOverflowError
StackOverflowError возникает, когда переполняется стек вызовов (stack memory). Обычно это происходит из-за глубокой или бесконечной рекурсии, когда метод вызывает сам себя, но нет условия выхода.

🔹 Причины:

  • Бесконечная рекурсия.
  • Слишком глубокий уровень рекурсивных вызовов.
  • Очень большие локальные переменные (занимают много места в стеке).

🔹 Как избежать?

  • Добавлять условие выхода в рекурсию.
  • Ограничивать глубину рекурсивных вызовов.
  • Использовать итерацию вместо рекурсии, если возможно.
  • Увеличить размер стека с помощью -Xss (не рекомендуется без необходимости).

OutOfMemoryError
OutOfMemoryError возникает, когда JVM не может выделить достаточно памяти в куче (Heap) для создания нового объекта.

🔹 Возможные причины:

  • Создание очень большого массива или объекта.
  • Утечки памяти (неочищенные ссылки на объекты).
  • Чрезмерное создание объектов без их удаления.
  • Ограничение памяти JVM (по умолчанию) — например, -Xmx256m.

🔹 Как избежать?

  • Оптимизировать управление памятью (использовать WeakReference, SoftReference).
  • Удалять ненужные объекты (list.clear(), null-ссылки).
  • Использовать профилировщики памяти (VisualVM, MAT).
  • Увеличить Heap Size (-Xmx1024m).

📌 Итоги

ОшибкаПричинаКак вызвать?Как исправить?
StackOverflowErrorПереполнение стека вызовов (бесконечная рекурсия).Метод вызывает сам себя бесконечно.Добавить условие выхода в рекурсию, увеличить стек (-Xss).
OutOfMemoryErrorНедостаток памяти в Heap (слишком много объектов).Создать огромный массив или бесконечно добавлять объекты.Использовать профилировщики, оптимизировать память, увеличить -Xmx.

Как вызвать StackOverflowError?
Простой пример бесконечной рекурсии:

public class StackOverflowExample {
    public static void recursiveMethod() {
        recursiveMethod(); // Метод вызывает сам себя бесконечно
    }
    
    public static void main(String[] args) {
        recursiveMethod();
    }
}

Результат:

Exception in thread "main" java.lang.StackOverflowError

Как вызвать OutOfMemoryError?
Пример создания слишком большого массива:

public class OOMExample {
    public static void main(String[] args) {
        int[] bigArray = new int[Integer.MAX_VALUE]; // Запрос огромного массива
    }
}

Результат:

Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit

Пример утечки памяти:

import java.util.ArrayList;
import java.util.List;

public class MemoryLeakExample {
    public static void main(String[] args) {
        List<int[]> list = new ArrayList<>();
        while (true) {
            list.add(new int[1000000]); // Создаем массивы без их удаления
        }
    }
}