Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Error в Java: определение и примеры
В Java существует чёткое разделение между Exception (исключение) и Error (ошибка). Это часто путают, но это совершенно разные вещи.
Различие между Exception и Error
Exception — это ошибка, которая может быть обработана приложением. Программист может её поймать и как-то отреагировать.
Error — это серьёзная проблема в работе JVM, которая не должна быть поймана. Если произошла Error, приложение находится в непредсказуемом состоянии и должно завершиться.
java.lang.Throwable
├── java.lang.Exception (нужно обрабатывать)
│ ├── IOException
│ ├── SQLException
│ └── ...
└── java.lang.Error (НЕ нужно обрабатывать)
├── OutOfMemoryError
├── StackOverflowError
└── ...
Примеры Error
1. OutOfMemoryError — самый частый случай
public class OutOfMemoryExample {
public static void main(String[] args) {
List<byte[]> list = new ArrayList<>();
while (true) {
// Выделяем 1 MB за каждую итерацию
list.add(new byte[1024 * 1024]);
// Рано или поздно кончится память в heap
}
// java.lang.OutOfMemoryError: Java heap space
}
}
Эта ошибка означает, что garbage collector не может освободить достаточно памяти. Приложение должно завершиться и освободить все ресурсы.
2. StackOverflowError — переполнение стека вызовов
public class StackOverflowExample {
public static void recursion() {
recursion(); // Бесконечная рекурсия
}
public static void main(String[] args) {
recursion();
// java.lang.StackOverflowError
}
}
Каждый вызов метода добавляет новый frame в стек. Если рекурсия не имеет базового случая, стек переполнится.
3. ExceptionInInitializerError — ошибка инициализации класса
public class BadInitialization {
static {
throw new RuntimeException("Критическая ошибка при инициализации");
}
}
public class Main {
public static void main(String[] args) {
try {
BadInitialization obj = new BadInitialization();
} catch (ExceptionInInitializerError e) {
// Обычно мы не ловим Error, но иногда приходится
e.printStackTrace();
}
}
}
4. NoClassDefFoundError — класс не найден в runtime
// Компилируется успешно, но если класс отсутствует в runtime:
public class Main {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("com.missing.Class");
} catch (ClassNotFoundException e) {
// Это Exception, а не Error!
}
}
}
// java.lang.NoClassDefFoundError: com/missing/Class
5. VirtualMachineError — ошибка JVM
// Редкий случай, когда JVM сама себе не может помочь
// Например, критическое падение в native коде
Когда ловить Error? (Очень редко!)
Обычно НЕ НУЖНО ловить Error. Но есть редкие случаи:
public class SafeMain {
public static void main(String[] args) {
try {
doSomethingCritical();
} catch (OutOfMemoryError e) {
// Логируем и грациозно завершаемся
System.err.println("Недостаточно памяти");
System.exit(1);
} catch (StackOverflowError e) {
System.err.println("Переполнение стека");
System.exit(1);
} catch (Error e) {
// Последняя линия защиты для критичных приложений
System.err.println("Критическая ошибка JVM");
System.exit(1);
}
}
}
Практический совет
Вывод: ловишь исключение — обрабатываешь её логично. Видишь Error — готовся к завершению приложения.
В 99% случаев нужно работать с Exception, а не с Error. Error — это сигнал, что что-то серьёзно не так в JVM или в памяти приложения.