Вопрос с собеседования · Java

Что такое class loader и как работает делегирование загрузки классов?

MiddleJVM и сборка мусора
Ещё спрашивают так:
  • Зачем загрузчики классов сначала делегируют загрузку родителю?
  • Зачем загрузчики классов сначала делегируют загрузку родителю (parent-first)?
Коротко

ClassLoader находит байт-код и превращает его в класс. Иерархия: Bootstrap (ядро JDK) → Platform (модули платформы) → Application (classpath). Модель parent-first: запрос сначала идёт к родителю, и только если тот не нашёл — загрузчик ищет сам.

  • Защита: свой java.lang.String в classpath не подменит системный
  • Класс в JVM определяется парой «полное имя + загрузчик»
  • Исключения: сервлет-контейнеры грузят классы приложения первыми (child-first)

А ещё Утечка загрузчика — источник OutOfMemoryError: Metaspace при передеплое

Подробно

Иерархия загрузчиков (Java 9+):

  • Bootstrap — встроенный в JVM, грузит java.base и ядро;
  • Platform — остальные модули Java SE и JDK;
  • Application (System) — классы из classpath и module path приложения.

Делегирование. loadClass сначала проверяет, не загружен ли класс, затем просит родителя, и только при неудаче вызывает свой findClass. Зачем:

  • безопасность — классы платформы всегда приходят от доверенного загрузчика, подменить java.lang.String нельзя;
  • единственность — базовый класс загружается один раз, а не каждым загрузчиком отдельно.

Идентичность класса. Один и тот же байт-код, загруженный двумя загрузчиками, — два разных класса. Отсюда «ClassCastException: Foo cannot be cast to Foo». На этом же построена изоляция: плагины и веб-приложения используют разные версии одной библиотеки.

Отступления от parent-first: сервлет-контейнеры (Tomcat) сначала ищут в WEB-INF приложения, чтобы его библиотеки не перекрывались серверными; OSGi и системы плагинов строят граф загрузчиков. Для SPI используют контекстный загрузчик потока (Thread.getContextClassLoader).

Загрузка ленивая: класс загружается и инициализируется при первом активном использовании.

Что хотят услышать

  • Иерархия загрузчиков.
  • Parent-first и его цель.
  • Идентичность класса.
  • Где правило нарушают.

Частые ошибки

  • Не знать, что класс определяется и загрузчиком.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗Загрузчик сначала ищет класс сам, а к родителю обращается, только если не нашёл
  • ✓Parent-first: запрос сначала уходит родителю, и только если тот не нашёл, загрузчик ищет сам
  • ✗Все классы грузит один загрузчик
  • ✗Класс определяется только полным именем, поэтому два загрузчика всегда дают один и тот же класс

Что спросят дальше

  • Что такое metaspace?
  • Почему два одинаковых класса из разных classloader несовместимы?
  • Почему контейнеры приложений отступают от parent-first?
  • Когда класс считается инициализированным?

Разбор темы

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования