Короткий ответ
ClassLoader — компонент JVM, отвечающий за загрузку классов: он находит бинарное представление класса (байт-код из .class-файла, JAR-архива, сети или БД) и создаёт объект java.lang.Class. Загрузка выполняется лениво — при первом использовании класса. Встроенные загрузчики работают по модели делегирования родителю: запрос уходит вверх по иерархии, и класс загружает первый загрузчик, который сможет его найти.
Как это работает подробнее
В JVM три встроенных загрузчика: Bootstrap ClassLoader (написан на нативном коде, загружает ядро JDK: rt.jar в Java 8 или базовые модули runtime image в Java 9+), Platform (в Java 8 — Extension) ClassLoader для расширений и платформенных библиотек и Application (System) ClassLoader для классов приложения из classpath.
По модели делегирования загрузчик сначала передаёт запрос родительскому загрузчику, и только если родитель вплоть до Bootstrap не нашёл класс, ищет его сам. Если класс не найден нигде — выбрасывается ClassNotFoundException.
- Из делегирования следуют видимость (классы родителя видны наследникам, но не наоборот) и уникальность (класс не загружается повторно, если его уже загрузил родитель).
- Собственный загрузчик создаётся наследованием от java.lang.ClassLoader, переопределением findClass() и получением Class из байтов через defineClass() — так работают Tomcat и серверы приложений для изоляции.
- Метаданные загруженных классов JVM хранит в области Metaspace.
Что использовать на практике
- Для изоляции версий библиотек и приложений (как в контейнерах) пишите собственные ClassLoader'ы.
- Для загрузки класса по имени используйте Class.forName() или ClassLoader.loadClass().
- При диагностике ClassNotFoundException проверяйте classpath и порядок делегирования в иерархии загрузчиков.