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

Что такое класс Error?

1.0 Junior🔥 161 комментариев
#Основы Java

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

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

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

Класс Error в Java — критические системные ошибки

Error — это базовый класс в Java, представляющий серьёзные, неустранимые ошибки, которые обычно указывают на проблемы на уровне виртуальной машины Java (JVM). Error наследуется из Throwable и не предназначен для перехвата в пользовательском коде.

Иерархия Throwable

// Полная иерархия
Throwable
  ├── Exception (проверяемые и непроверяемые исключения)
  │   ├── IOException
  │   ├── SQLException
  │   └── RuntimeException (непроверяемые)
  │       ├── NullPointerException
  │       └── IllegalArgumentException
  └── Error (серьёзные ошибки виртуальной машины)
      ├── OutOfMemoryError
      ├── StackOverflowError
      └── VirtualMachineError

Основные различия между Error и Exception

ПараметрErrorException
НазначениеСистемные ошибки JVMОшибки приложения
ВосстанавливаемостьНе восстанавливаемыВосстанавливаемы
ПерехватНе следует перехватыватьНужно обрабатывать
ПримерыOutOfMemory, StackOverflowNullPointer, IO, SQL
КонтрольВне контроля приложенияКонтроль приложения

Основные типы Error

OutOfMemoryError — исчерпана память JVM:

public class OutOfMemoryExample {
    public static void main(String[] args) {
        try {
            List<byte[]> memory = new ArrayList<>();
            // Выделяем память по 1MB в цикле
            while (true) {
                memory.add(new byte[1024 * 1024]); // 1MB
                System.out.println("Allocated: " + memory.size() + "MB");
            }
        } catch (OutOfMemoryError e) {
            System.err.println("Out of memory: " + e.getMessage());
            // Обычно здесь можно только логировать и завершить приложение
        }
    }
}

StackOverflowError — переполнение стека вызовов:

public class StackOverflowExample {
    public static void infiniteRecursion(int n) {
        infiniteRecursion(n + 1); // Бесконечная рекурсия
    }
    
    public static void main(String[] args) {
        try {
            infiniteRecursion(0);
        } catch (StackOverflowError e) {
            System.err.println("Stack overflow: " + e.getMessage());
            // Проблема в коде — бесконечная рекурсия
        }
    }
}

VirtualMachineError — внутренняя ошибка JVM:

// Может быть вызвана различными проблемами JVM
// java.lang.InternalError
// java.lang.UnknownError
public class VirtualMachineErrorExample {
    public static void main(String[] args) {
        try {
            // Это очень редко в нормальной работе JVM
            throw new InternalError("JVM internal error");
        } catch (InternalError e) {
            System.err.println("VM error: " + e.getMessage());
        }
    }
}

NoClassDefFoundError — класс не найден при загрузке:

public class ClassLoadingExample {
    public static void main(String[] args) {
        try {
            // Попытка загрузить класс, который не существует
            Class<?> clazz = Class.forName("com.nonexistent.MyClass");
        } catch (ClassNotFoundException e) {
            System.err.println("Class not found: " + e.getMessage());
        } catch (NoClassDefFoundError e) {
            // Класс был скомпилирован, но не найден при загрузке
            System.err.println("No class def found: " + e.getMessage());
        }
    }
}

AssertionError — ошибка утверждения (assertions):

public class AssertionErrorExample {
    public static void main(String[] args) {
        int age = -5;
        
        try {
            // assert — проверка условия
            assert age >= 0 : "Age cannot be negative";
        } catch (AssertionError e) {
            System.err.println("Assertion failed: " + e.getMessage());
        }
    }
}

Когда НЕ следует перехватывать Error

public class BadErrorHandling {
    public static void main(String[] args) {
        try {
            // Плохая практика — ловить Error
            someOperation();
        } catch (Error e) {
            // Не делайте так! Error указывает на критическую проблему
            System.out.println("Error occurred");
        }
    }
    
    static void someOperation() {
        // OutOfMemoryError — нельзя восстановиться
        throw new OutOfMemoryError();
    }
}

Правильный подход к обработке ошибок

public class ProperErrorHandling {
    private static final org.slf4j.Logger logger = 
        org.slf4j.LoggerFactory.getLogger(ProperErrorHandling.class);
    
    public static void main(String[] args) {
        try {
            process();
        } catch (Exception e) {
            // Перехватываем только Exception
            logger.error("Application error", e);
            // Пытаемся восстановиться
        } catch (OutOfMemoryError e) {
            // Если перехватили OOM, можно попытаться очистить ресурсы
            logger.error("Out of memory, shutting down", e);
            System.exit(1); // Завершаем приложение
        }
    }
    
    static void process() throws Exception {
        // Работа с Exception, не с Error
    }
}

Exception vs Error в многопоточной среде

public class ThreadErrorHandling {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                // Может быть OutOfMemoryError в потоке
                List<byte[]> memory = new ArrayList<>();
                while (true) {
                    memory.add(new byte[1024 * 1024]);
                }
            } catch (OutOfMemoryError e) {
                // OutOfMemoryError повалит весь поток
                System.err.println("Thread OOM: " + e.getMessage());
            }
        });
        
        thread.setUncaughtExceptionHandler((t, e) -> {
            // Обработчик невойманных исключений
            System.err.println("Uncaught in thread: " + e.getClass());
        });
        
        thread.start();
    }
}

Жизненный цикл при Error

public class ErrorLifecycle {
    public static void main(String[] args) {
        try {
            System.out.println("1. Start");
            
            // Можем перехватить OutOfMemoryError
            try {
                List<byte[]> memory = new ArrayList<>();
                while (true) {
                    memory.add(new byte[1024 * 1024]);
                }
            } catch (OutOfMemoryError e) {
                System.out.println("2. Caught OutOfMemoryError");
                memory = null; // Очищаем ссылку
                System.gc(); // Попробуем сборку мусора
                // Но обычно это не помогает
            }
            
            System.out.println("3. Continuing after OOM");
        } catch (Exception e) {
            System.out.println("4. Exception caught");
        } finally {
            System.out.println("5. Finally block");
        }
    }
}

Сравнение с RuntimeException

public class ComparisonWithRuntimeException {
    
    // RuntimeException — это Exception, её нужно обрабатывать
    public static void methodWithRuntimeException() {
        List<String> list = null;
        try {
            list.size(); // NullPointerException (наследник RuntimeException)
        } catch (RuntimeException e) {
            System.out.println("Caught runtime exception: " + e.getMessage());
            // Можем продолжить работу
        }
    }
    
    // Error — это не Exception, её обычно НЕ перехватывают
    public static void methodWithError() {
        try {
            throw new StackOverflowError();
        } catch (StackOverflowError e) {
            // Перехватили, но мало чем поможет
            System.err.println("Stack overflow");
            System.exit(1);
        }
    }
}

Лучшие практики

  1. Не ловите Error: Error указывает на критическую проблему, которую невозможно исправить в приложении
// Плохо
try {
    someCode();
} catch (Throwable t) {
    // Может поймать Error!
}

// Хорошо
try {
    someCode();
} catch (Exception e) {
    // Ловим только Exception
}
  1. Логируйте системные ошибки: Если Error всё же произошёл, нужно его залогировать
Thread.currentThread().setUncaughtExceptionHandler((thread, exception) -> {
    if (exception instanceof Error) {
        logger.error("Critical system error", exception);
        System.exit(1);
    }
});
  1. Предотвращайте ошибки: Управляйте памятью, избегайте глубокой рекурсии
// Предотвращение StackOverflowError
public long factorial(int n) {
    if (n > 5000) {
        throw new IllegalArgumentException("Value too large for recursion");
    }
    return n <= 1 ? 1 : n * factorial(n - 1);
}

Заключение

Error — это серьёзные системные ошибки JVM, которые обычно указывают на неисправимые проблемы. В отличие от Exception, Error не следует ловить и обрабатывать в приложении. Правильный подход — предотвращать ошибки через управление ресурсами и правильное программирование, а не пытаться их перехватывать.