Иерархия ClassLoader и пользовательские загрузчики
Поймите работу загрузчиков классов начальной загрузки, платформы и приложения и напишите собственный ClassLoader.
«Иерархия ClassLoader и пользовательские загрузчики» — бесплатный урок Java Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.
Иерархия ClassLoader
JVM использует иерархию ClassLoader. У каждого загрузчика есть родитель; прежде чем загрузить класс самостоятельно, он делегирует загрузку родителю (модель делегирования сначала родителю).
Загрузчик Bootstrap
Загрузчик Bootstrap загружает основные классы JDK (java.lang.*, java.util.*). Он реализован в машинном коде и не имеет родительского Java-загрузчика; getParent() возвращает null.
ClassLoader cl = String.class.getClassLoader();
System.out.println(cl); // null (bootstrap ClassLoader)Платформенный ClassLoader (Java 9+)
Платформенный ClassLoader (ранее ClassLoader расширений) загружает модули из JDK, не входящие в начальный набор (java.sql, java.xml и т. д.). Его родитель — загрузчик Bootstrap.
ClassLoader platform = ClassLoader.getPlatformClassLoader();
System.out.println(platform.getClass().getName());
// jdk.internal.loader.ClassLoaders$PlatformClassLoaderClassLoader приложения (системный)
ClassLoader приложения загружает классы приложения из пути классов (-cp / CLASSPATH). Его родитель — платформенный ClassLoader. Это загрузчик по умолчанию для пользовательского кода.
ClassLoader app = ClassLoader.getSystemClassLoader();
System.out.println(app.getClass().getName());
// jdk.internal.loader.ClassLoaders$AppClassLoaderДелегирование сначала родителю
При загрузке com.example.MyService AppClassLoader сначала обращается к своему родителю (платформенному), который обращается к Bootstrap. Только если ни один из родителей не может загрузить класс, дочерний загрузчик пытается загрузить его самостоятельно.
Идентичность классов и ClassLoaders
Два класса с одним именем, загруженные разными ClassLoaders, считаются разными типами. Приведение одного к другому вызывает ClassCastException — это важно в системах плагинов и OSGi.
// Loaded by two different loaders → different Class objects
Class<?> c1 = loader1.loadClass("com.example.Plugin");
Class<?> c2 = loader2.loadClass("com.example.Plugin");
System.out.println(c1 == c2); // false!Создание собственного ClassLoader
Расширьте ClassLoader и переопределите findClass(String name). Прочитайте байт-код из пользовательского источника (зашифрованного JAR, сети или базы данных) и вызовите defineClass.
public class EncryptedClassLoader extends ClassLoader {
public EncryptedClassLoader(ClassLoader parent) { super(parent); }
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] bytes = decrypt(readBytecodeFromVault(name));
return defineClass(name, bytes, 0, bytes.length);
}
}URL ClassLoader: загрузка из JAR-файлов
URLClassLoader загружает классы из списка URL (путей к файлам или HTTP-адресов). Это полезно для систем плагинов, которые добавляют JAR-файлы во время выполнения.
URL[] urls = { new File("plugins/my-plugin.jar").toURI().toURL() };
try (URLClassLoader loader = new URLClassLoader(urls, getClass().getClassLoader())) {
Class<?> cls = loader.loadClass("com.example.PluginImpl");
Plugin plugin = (Plugin) cls.getDeclaredConstructor().newInstance();
plugin.start();
}Закрытие ClassLoaders
Всегда закрывайте URLClassLoader после завершения работы — он удерживает JAR-файлы открытыми. После закрытия JAR-файлы можно удалить или обновить. Используйте конструкцию try с ресурсами.
Делегирование сначала дочернему загрузчику (изолированная загрузка)
Некоторые контейнеры (Tomcat, Spring Boot с JAR-файлом, содержащим зависимости) инвертируют иерархию: дочерний загрузчик пытается загрузить класс первым и обращается к родителю только при отсутствии класса. Это изолирует версии библиотек между веб-приложениями.
Утечки ClassLoader
Загрузчик классов освобождается сборщиком мусора только тогда, когда недоступен ни один загруженный им класс. Статические поля, удерживающие объекты из загруженного класса, не дают загрузчику освободиться — это распространённая утечка при переразвертывании приложения.
Быстрая проверка
Что делает ClassLoader, прежде чем попытаться загрузить класс самостоятельно?
Итоги
Трёхуровневая иерархия: Bootstrap → Platform → Application. Делегирование сначала родителю предотвращает дублирование классов. Пользовательские загрузчики переопределяют findClass. Используйте URLClassLoader для систем плагинов. Закрывайте загрузчики, чтобы предотвратить утечки.
Часто задаваемые вопросы
Урок «Иерархия ClassLoader и пользовательские загрузчики» бесплатный?
Да — полный текст урока «Иерархия ClassLoader и пользовательские загрузчики» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.
Чему я научусь в уроке «Иерархия ClassLoader и пользовательские загрузчики»?
Поймите работу загрузчиков классов начальной загрузки, платформы и приложения и напишите собственный ClassLoader. Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Java Academy?
Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Иерархия ClassLoader и пользовательские загрузчики»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Java Academy?
Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Этапы загрузки классов: загрузка, связывание, инициализация
- Иерархия ClassLoader и пользовательские загрузчики
- Просмотр байткода с помощью javap
- JIT-компиляция и многоуровневая компиляция