Ответ
Загрузка классов в Java — это процесс поиска байт-кода класса (файла .class) и создания объекта java.lang.Class. Этим управляет иерархия ClassLoader'ов, работающих по модели делегирования (parent-delegation).
Иерархия встроенных загрузчиков:
- Bootstrap ClassLoader (null): Написан на нативном коде. Загружает основные классы Java Core (
java.lang.*,java.util.*и др.) изrt.jarи других системных библиотек. - Platform (Extension) ClassLoader: Загружает классы из каталогов расширений (
jre/lib/extили указанных черезjava.ext.dirs). - Application (System) ClassLoader: Загружает классы из classpath (параметр
-cp, переменнаяCLASSPATH).
Модель делегирования «снизу вверх»:
Когда Application ClassLoader получает запрос на загрузку класса:
- Он не ищет класс сразу. Сначала он делегирует запрос своему родителю —
Platform ClassLoader. Platform ClassLoader, в свою очередь, делегирует запрос своему родителю —Bootstrap ClassLoader.- Если
Bootstrapне может найти класс (не в его области), управление возвращаетсяPlatform, который пытается загрузить класс сам. - Если и
Platformне может, запрос возвращаетсяApplication, который ищет класс в classpath.
Пример кода:
// Явная загрузка класса
Class<?> clazz = Class.forName("com.example.MyClass");
// Получение загрузчика класса
ClassLoader loader = MyClass.class.getClassLoader();
System.out.println(loader); // sun.misc.Launcher$AppClassLoader
System.out.println(loader.getParent()); // sun.misc.Launcher$ExtClassLoader
System.out.println(loader.getParent().getParent()); // null (Bootstrap)
Зачем нужна модель делегирования?
- Безопасность: Не позволяет пользовательскому классу заменить системный (например, свой
java.lang.String). - Уникальность: Класс загружается единожды своим «родительским» загрузчиком, что предотвращает конфликты.
- Иерархия видимости: Классы, загруженные родительским загрузчиком, видны дочерним, но не наоборот.
Важные исключения:
ClassNotFoundException: Загрузчик не смог найти байт-код класса.NoClassDefFoundError: Класс был найден при компиляции, но не доступен во время выполнения (например, ошибка в статическом инициализаторе).