Загрузчик классов Java , часть среды выполнения Java , динамически загружает классы Java в виртуальную машину Java . [1] Обычно классы загружаются только по требованию . Виртуальная машина будет загружать только файлы классов, необходимые для выполнения программы. [2] Системе выполнения Java не нужно знать о файлах и файловых системах, поскольку это делегировано загрузчику классов.
Библиотека программного обеспечения представляет собой набор связанного объектного кода . В языке Java библиотеки обычно упаковываются в файлы JAR . Библиотеки могут содержать объекты разных типов. Наиболее важным типом объекта, содержащегося в файле JAR, является класс Java . Класс можно рассматривать как именованную единицу кода. Загрузчик классов отвечает за поиск библиотек, чтение их содержимого и загрузку классов, содержащихся в библиотеках. Эта загрузка обычно выполняется «по требованию», то есть она не происходит до тех пор, пока класс не будет вызван программой. Класс с заданным именем может быть загружен только один раз заданным загрузчиком классов.
Каждый класс Java должен быть загружен загрузчиком классов. [3] [4] Кроме того, программы Java могут использовать внешние библиотеки (то есть библиотеки, написанные и предоставленные кем-то, кроме автора программы) или они могут состоять, по крайней мере частично, из нескольких библиотек.
При запуске JVM используются три загрузчика классов: [5] [6] [2]
Загрузчик классов bootstrap загружает основные библиотеки Java [fn 1] , расположенные в каталоге <JAVA_HOME>/jre/lib
(или <JAVA_HOME>/jmods>
для Java 9 и выше). Этот загрузчик классов, являющийся частью основной JVM, написан на машинном коде. Загрузчик классов bootstrap не связан ни с одним ClassLoader
объектом. [2] Например, возвращает . [2]StringBuilder.class.getClassLoader()
null
Загрузчик классов расширений загружает код в каталоги расширений ( <JAVA_HOME>/jre/lib/ext
, [5] или любой другой каталог, указанный системным java.ext.dirs
свойством).
Загрузчик системных классов загружает код, найденный в java.class.path
, который сопоставляется с CLASSPATH
переменной среды .
Загрузчик классов Java написан на Java. Поэтому можно создать собственный загрузчик классов, не разбираясь в тонкостях виртуальной машины Java. Помимо загрузчика классов Bootstrap, каждый загрузчик классов Java имеет родительский загрузчик классов. [7] Родительский загрузчик классов определяется, когда создается новый загрузчик классов или устанавливается в качестве системного загрузчика классов виртуальной машины по умолчанию.
Это позволяет (например):
Серверы приложений Jakarta EE (ранее Java EE и J2EE) обычно загружают классы из развернутого архива WAR или EAR с помощью дерева загрузчиков классов, изолируя приложение от других приложений, но разделяя классы между развернутыми модулями. Так называемые « контейнеры сервлетов » обычно реализуются в терминах нескольких загрузчиков классов. [4] [9]
JAR hell — это термин, похожий на DLL hell, используемый для описания всех возможных ситуаций, в которых процесс загрузки классов может закончиться неудачей. [10] JAR hell может возникнуть тремя способами:
OSGi Alliance определил (начиная с JSR 8 в 1998 году) модульную структуру, которая направлена на решение проблемы JAR-ада для текущих и будущих виртуальных машин в ME, SE и EE, которая широко принята. Используя метаданные в манифесте JAR , файлы JAR (называемые пакетами) подключаются на основе пакетов. Пакеты могут экспортировать пакеты, импортировать пакеты и сохранять пакеты приватными, предоставляя основные конструкции модульности и управления зависимостями версий.
Java 9 представила Java Platform Module System в 2017 году. Она определяет формат распределения для коллекций кода Java и связанных с ними ресурсов. Она также определяет репозиторий для хранения этих коллекций, или модулей , и определяет, как их можно обнаружить, загрузить и проверить на целостность. Она включает такие функции, как пространства имен, с целью исправления некоторых недостатков существующего формата JAR . Java Platform Module System следует философии, отличной от архитектуры OSGi, которая направлена на обеспечение модульности для Java Runtime Environment обратно совместимым способом, который использует механизм загрузки классов по умолчанию, предоставляемый JRE. Однако, поскольку Java Platform Module System не предлагает возможности контролируемого сосуществования библиотек с разными версиями, она не полностью решает проблему JAR hell. [12]