ClassLoader — это специальный компонент в JVM, отвечающий за загрузку байт-кода классов в память при их первом использовании. Он позволяет подгружать классы динамически из различных источников (файловой системы, сети, архива и т.п.).
Типы загрузчиков классов:
jre/lib/ext.ClassLoader реализует делегирование: сначала пытается загрузить класс родительский загрузчик (parent-first), только если не удалось — ищет сам.
Изоляция классов: Каждый загрузчик классов создаёт свою "область видимости" классов. Два одинаковых по имени класса, загруженные разными загрузчиками, считаются разными типами внутри JVM.
Пример создания собственного загрузчика:
class MyClassLoader extends ClassLoader { @Override protected Class<?> findClass(String name) throws ClassNotFoundException { // Ваш код по поиску и загрузке байт-кода класса return super.findClass(name); } }
Могут ли два одинаковых по имени класса, загруженные разными загрузчиками, считаться одним классом внутри JVM?
Ответ: Нет! JVM считает класс уникальным по паре (полное имя класса, загрузчик классов). Поэтому одни и те же классы, загруженные разными загрузчиками, будут считаться разными.
История
В enterprise-приложении с поддержкой plug-in архитектуры плагины грузились отдельными загрузчиками классов. В результате попытка передачи объекта типа интерфейса (PluginInterface) между основным приложением и плагином вызывала ClassCastException, потому что один и тот же интерфейс был загружен разными загрузчиками.
История
При использовании кастомного загрузчика классов не было реализовано делегирование к родительскому загрузчику. Это приводило к повторной загрузке стандартных библиотечных классов, что вызвало странные ошибки ClassCastException и LinkageError.
История
В большом Java EE-сервере разные приложения грузили свои версии одной и той же библиотеки. Небрежность в настройке цепочки загрузчиков привела к тому, что классы пересекались между приложениями, что однажды вызвало massive memory leak и сбои из-за конфликтов версий.