← Назад к вопросам

Что такое ClassLoader в Java? Какие типы загрузчиков классов существуют?

1.0 Junior🔥 161 комментариев
#Soft Skills и карьера

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое ClassLoader в Java? Какие типы загрузчиков классов существуют?

ClassLoader — это механизм, отвечающий за загрузку Java классов в оперативную память во время выполнения приложения. Это фундаментальная часть Java Virtual Machine (JVM), которая управляет динамической загрузкой кода.

Зачем нужен ClassLoader?

Java работает с байт-кодом (.class файлы). Когда JVM начинает выполнять программу, она не загружает ВСЕ классы сразу. Вместо этого используется ленивая загрузка:

public class Main {
    public static void main(String[] args) {
        // ClassLoader загружает Main класс
        // При вызове этого метода загрузится DatabaseConnection
        DatabaseConnection db = new DatabaseConnection();
    }
}

Когда класс впервые нужен — ClassLoader загружает его и кеширует в памяти.

Три встроенных типа ClassLoader

1. Bootstrap ClassLoader (Приморидиальный загрузчик)

Загружает ядро Java — классы из java.lang, java.util и прочие системные классы из папки JAVA_HOME/lib:

ClassLoader bootstrapLoader = null;
String className = "java.lang.String";
Class<?> stringClass = Class.forName(className);
System.out.println(stringClass.getClassLoader());  // null — Bootstrap ClassLoader

Особенности:

  • Написан на C++, не на Java
  • Загружает только системные классы JDK
  • Возвращает null при обращении к getClassLoader()
  • Наивысший приоритет

2. Extension ClassLoader (Загрузчик расширений)

Загружает классы из папки JAVA_HOME/lib/ext и из переменной окружения java.ext.dirs:

ClassLoader extLoader = ClassLoader.getSystemClassLoader().getParent();
String className = "com.sun.com.sun.org.apache.xerces.internal.impl.dv.dtypes.StringDV";
try {
    Class<?> extClass = Class.forName(className);
    System.out.println(extClass.getClassLoader());  // ExtClassLoader
} catch (ClassNotFoundException e) {
    System.out.println("Класс расширения не найден");
}

Особенности:

  • Загружает дополнительные библиотеки
  • Наследует от SecureClassLoader
  • Используется для модулей и расширений
  • В Java 9+ переименован в PlatformClassLoader

3. Application ClassLoader (Загрузчик приложения)

Загружает классы из CLASSPATH — это те классы, которые вы пишете и библиотеки в проекте:

public class MyClass {
    public static void main(String[] args) {
        // Application ClassLoader загружает MyClass
        ClassLoader appLoader = MyClass.class.getClassLoader();
        System.out.println(appLoader.getClass().getName());  
        // sun.misc.Launcher$AppClassLoader
    }
}

Особенности:

  • Загружает пользовательские классы и библиотеки
  • Наследует от SecureClassLoader
  • Это стандартный загрузчик для приложений

Иерархия и делегирование

ClassLoader работают по принципу делегирования (delegation):

┌─────────────────────────────┐
│  Application ClassLoader    │
└─────────────────────────────┘
              ↓
┌─────────────────────────────┐
│  Extension ClassLoader      │
└─────────────────────────────┘
              ↓
┌─────────────────────────────┐
│  Bootstrap ClassLoader      │
└─────────────────────────────┘

Когда запрашиваете класс:

  1. Application ClassLoader проверяет свой кеш
  2. Если не найден, делегирует Extension ClassLoader
  3. Extension делегирует Bootstrap
  4. Bootstrap загружает, если это системный класс
  5. Если не нашёл — ошибка в Extension
  6. Если не нашёл — загружает Application
public class ClassLoaderExample {
    public static void main(String[] args) throws ClassNotFoundException {
        // Загружает java.lang.String через Bootstrap
        Class<?> stringClass = Class.forName("java.lang.String");
        System.out.println(stringClass.getClassLoader());  // null
        
        // Загружает MyClass через Application
        Class<?> myClass = Class.forName("com.example.MyClass");
        System.out.println(myClass.getClassLoader());  // AppClassLoader
        
        // Загружает MyClass явно через конкретный загрузчик
        ClassLoader appLoader = MyClass.class.getClassLoader();
        Class<?> explicit = appLoader.loadClass("com.example.AnotherClass");
    }
}

Методы загрузки классов

Метод 1: Через Class.forName() — использует текущий ClassLoader

Class<?> clazz = Class.forName("java.sql.Driver");
// Использует ClassLoader текущего класса

Метод 2: Через явный ClassLoader

ClassLoader loader = MyClass.class.getClassLoader();
Class<?> clazz = Class.forName("com.example.MyClass", true, loader);

Метод 3: Через loadClass() прямо на ClassLoader

ClassLoader loader = ClassLoader.getSystemClassLoader();
Class<?> clazz = loader.loadClass("java.util.ArrayList");

Кастомный ClassLoader

Вы можете создать собственный загрузчик для специальных сценариев:

public class CustomClassLoader extends ClassLoader {
    private String classPath;
    
    public CustomClassLoader(String classPath) {
        this.classPath = classPath;
    }
    
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // Читаем .class файл с диска
        byte[] classBytes = readClassBytes(name);
        if (classBytes == null) {
            throw new ClassNotFoundException(name);
        }
        // Преобразуем байт-код в Class
        return defineClass(name, classBytes, 0, classBytes.length);
    }
    
    private byte[] readClassBytes(String className) {
        // Логика чтения .class файла
        return null;
    }
}

// Использование
CustomClassLoader loader = new CustomClassLoader("/path/to/classes");
Class<?> clazz = loader.loadClass("com.example.MyClass");
Object instance = clazz.getDeclaredConstructor().newInstance();

Практические применения

  • Фреймворки: Spring использует кастомные ClassLoader для динамической загрузки бинов
  • Плагины: OSGI и подобные системы загружают/выгружают модули
  • Горячая замена кода: некоторые приложения перезагружают классы без перезапуска
  • Изоляция: разные ClassLoader для разных модулей приложения

Проблемы и граблиостях

// Утечка памяти — класс остаётся в памяти
ClassLoader cl = new URLClassLoader(urls);
Class<?> clazz = cl.loadClass("MyClass");
// cl больше не нужен, но MyClass остаётся в памяти!

// Решение: явно закрыть
if (cl instanceof Closeable) {
    ((Closeable) cl).close();
}

ClassLoader — это один из ключевых механизмов Java, позволяющих реализовывать динамическую загрузку кода и создавать гибкие, расширяемые приложения.

Что такое ClassLoader в Java? Какие типы загрузчиков классов существуют? | PrepBro