Расскажи про классы-загрузчики и про динамическую загрузку классов
Основа работы с классами в Java — классы-загрузчики, обычные Java-объекты, предоставляющие интерфейс для поиска и создания объекта класса по его имени во время работы приложения.
В начале работы программы создается 3 основных загрузчика классов:
- базовый загрузчик (bootstrap/primordial). Загружает основные системные и внутренние классы JDK (Core API - пакеты
java.*
(rt.jar
иi18n.jar
) . Важно заметить, что базовый загрузчик является «Изначальным» или «Корневым» и частью JVM, вследствие чего его нельзя создать внутри кода программы. - загрузчик расширений (extention). Загружает различные пакеты расширений, которые располагаются в директории
<JAVA_HOME>/lib/ext
или другой директории, описанной в системном параметреjava.ext.dirs
. Это позволяет обновлять и добавлять новые расширения без необходимости модифицировать настройки используемых приложений. Загрузчик расширений реализован классомsun.misc.Launcher$ExtClassLoader
. - системный загрузчик (system/application). Загружает классы, пути к которым указаны в переменной окружения
CLASSPATH
или пути, которые указаны в командной строке запуска JVM после ключей-classpath
или-cp
. Системный загрузчик реализован классомsun.misc.Launcher$AppClassLoader
.
Загрузчики классов являются иерархическими: каждый из них (кроме базового) имеет родительский загрузчик и в большинстве случаев, перед тем как попробовать загрузить класс самостоятельно, он посылает вначале запрос родительскому загрузчику загрузить указанный класс. Такое делегирование позволяет загружать классы тем загрузчиком, который находится ближе всего к базовому в иерархии делегирования. Как следствие поиск классов будет происходить в источниках в порядке их доверия: сначала в библиотеке Core API, потом в папке расширений, потом в локальных файлах CLASSPATH
.
Процесс загрузки класса состоит из трех частей:
- Loading – на этой фазе происходит поиск и физическая загрузка файла класса в определенном источнике (в зависимости от загрузчика). Этот процесс определяет базовое представление класса в памяти. На этом этапе такие понятия как «методы», «поля» и т. д. пока не известны.
- Linking – процесс, который может быть разбит на 3 части:
- Bytecode verification – проверка байт-кода на соответствие требованиям, определенным в спецификации JVM.
- Class preparation – создание и инициализация необходимых структур, используемых для представления полей, методов, реализованных интерфейсов и т.п., определенных в загружаемом классе.
- Resolving – загрузка набора классов, на которые ссылается загружаемый класс.
- Initialization – вызов статических блоков инициализации и присваивание полям класса значений по умолчанию.
Динамическая загрузка классов в Java имеет ряд особенностей:
- отложенная (lazy) загрузка и связывание классов. Загрузка классов производится только при необходимости, что позволяет экономить ресурсы и распределять нагрузку.
- проверка корректности загружаемого кода (type safeness). Все действия связанные с контролем использования типов производятся только во время загрузки класса, позволяя избежать дополнительной нагрузки во время выполнения кода.
- программируемая загрузка. Пользовательский загрузчик полностью контролирует процесс получения запрошенного класса — самому ли искать байт-код и создавать класс или делегировать создание другому загрузчику. Дополнительно существует возможность выставлять различные атрибуты безопасности для загружаемых классов, позволяя таким образом работать с кодом из ненадежных источников.
- множественные пространства имен. Каждый загрузчик имеет своё пространство имён для создаваемых классов. Соответственно, классы, загруженные двумя различными загрузчиками на основе общего байт-кода, в системе будут различаться.
Существует несколько способов инициировать загрузку требуемого класса:
- явный: вызов
ClassLoader.loadClass()
илиClass.forName()
(по умолчанию используется загрузчик, создавший текущий класс, но есть возможность и явного указания загрузчика); - неявный: когда для дальнейшей работы приложения требуется ранее не использованный класс, JVM инициирует его загрузку.
Oct. 23, 2023, Источник