Ответ
ClassLoader — это компонент JRE, отвечающий за динамическую загрузку классов. Его архитектура состоит из следующих ключевых частей:
1. Иерархия загрузчиков (родительское делегирование)
- Bootstrap ClassLoader (Нативный): Загружает основные классы Java (
java.lang.*,java.util.*и др.) изrt.jarили модулей. Реализован на нативном коде. - Platform (Extension) ClassLoader: Загружает классы из стандартных расширений (ранее
jre/lib/ext) или модулей платформы. Родитель — Bootstrap. - System (Application) ClassLoader: Загружает классы из classpath приложения (
-cp,-classpath). Родитель — Platform ClassLoader. - Пользовательские (кастомные) ClassLoader'ы: Создаются разработчиками, обычно родителем указывается System ClassLoader.
2. Механизм делегирования
При запросе на загрузку класса загрузчик сначала делегирует запрос своему родителю. Только если родительская цепочка не смогла загрузить класс, текущий загрузчик пытается сделать это сам через метод findClass().
3. Ключевые методы класса java.lang.ClassLoader
loadClass(String name)— основной публичный метод, реализующий логику делегирования и вызоваfindClass.findClass(String name)— метод, который должен быть переопределен в кастомном загрузчике для поиска и определения байт-кода класса.defineClass(String name, byte[] b, int off, int len)— финальный метод, преобразующий массив байтов в объектClass<?>внутри JVM.getParent()— возвращает родительский загрузчик.
Пример кастомного ClassLoader:
public class MyClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// 1. Загрузить байт-код класса из нестандартного места (файл, сеть)
byte[] classBytes = loadClassBytesFromCustomSource(name);
if (classBytes == null) {
throw new ClassNotFoundException(name);
}
// 2. Преобразовать байты в Class-объект
return defineClass(name, classBytes, 0, classBytes.length);
}
private byte[] loadClassBytesFromCustomSource(String name) { /* ... */ }
}