Спецификация Java 11: 12.2. Загрузка классов и интерфейсов

Загрузка относится к процессу поиска двоичной формы класса или типа интерфейса с определенным именем, возможно, путем его вычисления на лету, но чаще путем извлечения двоичного представления, ранее вычисленного из исходного кода компилятором Java, и построения, из этой двоичной формы объект Class, представляющий класс или интерфейс.

Точная семантика загрузки дана в главе 5 спецификации виртуальной машины Java, Java SE 11 Edition. Здесь мы представляем обзор процесса с точки зрения языка программирования Java.

Двоичный формат класса или интерфейса обычно является форматом файла класса, описанным в спецификации виртуальной машины Java, Java SE 11 Edition, упомянутой выше, но возможны и другие форматы, при условии, что они соответствуют требованиям, указанным в §13.1. Метод defineClass класса ClassLoader может использоваться для создания объектов класса из двоичных представлений в формате файла class.

Хорошо работающие загрузчики классов поддерживают следующие свойства:

  • С таким же именем хороший загрузчик классов всегда должен возвращать один и тот же объект класса.
  • Если загрузчик классов L1 делегирует загрузку класса C другому загрузчику L2, то для любого типа T, который встречается как прямой суперкласс или прямой суперинтерфейс C, или как тип поля в C, или как тип формальный параметр метода или конструктора в C или как возвращаемый тип метода в C, L1 и L2 должен возвращать один и тот же объект класса.

Злоумышленник-загрузчик классов может нарушить эти свойства. Однако это не могло подорвать безопасность системы типов, потому что виртуальная машина Java защищает от этого.

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

12.2.1. Процесс загрузки

Процесс загрузки реализуется классом ClassLoader и его подклассами.

Различные подклассы ClassLoader могут реализовывать разные политики загрузки. В частности, загрузчик классов может кэшировать двоичные представления классов и интерфейсов, предварительно выбирать их в зависимости от ожидаемого использования или загружать группу связанных классов вместе. Эти действия могут быть не полностью прозрачными для работающего приложения, если, например, недавно скомпилированная версия класса не найдена, поскольку более старая версия кэшируется загрузчиком классов. Однако загрузчик классов обязан отражать ошибки загрузки только в тех точках программы, где они могли возникнуть без предварительной выборки или групповой загрузки.

Если во время загрузки класса возникает ошибка, то экземпляр одного из следующих подклассов класса LinkageError будет брошен в любой точке программы, которая (прямо или косвенно) использует тип:

  • ClassCircularityError: класс или интерфейс не могут быть загружены, потому что это будет его собственный суперкласс или суперинтерфейс (§8.1.4, §9.1.3, §13.4.4).
  • ClassFormatError: двоичные данные, предназначенные для указания запрошенного скомпилированного класса или интерфейса, имеют неправильный формат.
  • NoClassDefFoundError: соответствующий загрузчик классов не может найти определение запрошенного класса или интерфейса.

Поскольку загрузка включает выделение новых структур данных, она может завершиться ошибкой OutOfMemoryError.


Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки