Spec-Zone .ru
спецификации, руководства, описания, API
Содержание | Предыдущий | Следующий | ИндексСпецификация Виртуальной машины JavaTM


ГЛАВА 5

Постоянное Разрешение Пула


Классы Java и интерфейсы динамически загружаются (§2.16.2), соединились (§2.16.3), и инициализировали (§2.16.4). Загрузка является процессом обнаружения двоичной формы класса или интерфейсного типа с определенным именем и построением, от той двоичной формы, a Class объект представить класс или интерфейс. Соединение является процессом взятия двоичной формы класса или интерфейсного типа и объединения этого в состояние времени выполнения виртуальной машины Java так, чтобы это могло быть выполнено. Инициализация класса состоит из выполнения его статических инициализаторов и инициализаторов для статических полей, объявленных в классе.

Виртуальная машина Java выполняет большинство аспектов этих процедур через операции на постоянном пуле (§4.4), структура данных времени выполнения на тип, которая служит многим из целей таблицы символов стандартного языка. Например, инструкции виртуальной машины Java, которые, возможно, иначе были разработаны, чтобы взять непосредственный числовой или строковые операнды вместо этого, выбирают свои операнды от постоянного пула. Классы, методы, и поля, ссылаемый ли от инструкций виртуальной машины Java или от других постоянных записей пула, называют, используя постоянный пул.

Компилятор Java не предполагает, чтобы знать путь, которым виртуальная машина Java размечает классы, интерфейсы, экземпляры класса, или массивы. Ссылки в постоянном пуле являются всегда первоначально символьными. Во время выполнения символьное представление ссылки в постоянном пуле используется, чтобы решить фактическое расположение объекта, на который ссылаются. Процесс динамичного определения конкретных значений из символьных ссылок в постоянном пуле известен как постоянное разрешение пула. Постоянное разрешение пула может включить загрузку того или большего количества классов или интерфейсов, соединение нескольких типов, и инициализация типов. Есть несколько видов постоянных записей пула, и детали разрешения не соглашаются с видом записи, которая будет разрешена.

Отдельные инструкции виртуальной машины Java, что ссылочные объекты в постоянном пуле ответственны за разрешение объектов, на которые они ссылаются. Постоянные записи пула, на которые ссылаются от других постоянных записей пула, разрешаются, когда относящаяся запись разрешается.

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

Постоянное разрешение пула обычно инициируется выполнением инструкции виртуальной машины Java, которая ссылается на постоянный пул. Вместо того, чтобы давать полное описание процесса разрешения, выполняемого инструкциями виртуальной машины Java в их отдельных описаниях, мы будем использовать эту главу, чтобы суммировать постоянный процесс разрешения пула. Мы определим ошибки, которые должны быть обнаружены, разрешая каждый вид постоянной записи пула, порядка, в котором на те ошибки нужно ответить, и ошибки добавленный ответ.

Когда ссылающийся от контекста определенных инструкций виртуальной машины Java, дополнительные ограничения помещаются в соединение операций. Например, getfield инструкция требует не только, чтобы постоянная запись пула для поля, на которое это ссылается, могла быть успешно разрешена, но также и что разрешенное поле не является классом (static) поле. Если это - поле класса, исключение должно быть выдано. Соединение исключений, которые являются определенными для выполнения определенной инструкции виртуальной машины Java, дается в описании той инструкции и не покрывается этим общим обсуждением постоянного разрешения пула. Отметьте, что такие исключения, хотя описано как часть выполнения инструкций виртуальной машины Java, а не постоянного разрешения пула, все еще должным образом считают отказом соединяющейся фазы выполнения виртуальной машины Java.

Документы спецификации виртуальной машины Java и заказы все исключения, которые могут возникнуть в результате постоянного разрешения пула. Это не передает под мандат, как они должны быть обнаружены, только что они должны быть. Кроме того, как упомянуто в §6.3, любой из ошибок виртуальной машины, перечисленных как подклассы VirtualMachineError может быть брошен в любое время во время постоянного разрешения пула.


5.1 Класс и Интерфейсное Разрешение

Постоянная запись пула, тегированная как CONSTANT_Class (§4.4.1) представляет класс или интерфейс. Различная ссылка инструкций виртуальной машины Java CONSTANT_Class записи в постоянном пуле класса, который является текущим после их выполнения (§3.6). Несколько других видов постоянных записей пула (§4.4.2) ссылка CONSTANT_Class записи и причина те классифицируют или соединяют интерфейсом со ссылками, которые будут разрешены, когда записи ссылки разрешаются. Например, перед ссылкой метода (a CONSTANT_Methodref постоянная запись пула), может быть разрешен, ссылка, которую она делает на класс метода (через class_index элемент постоянной записи пула), должен сначала быть разрешен.

Если класс или интерфейс уже не были разрешены, детали процесса разрешения зависят от того, какой объект представляется CONSTANT_Class разрешаемая запись. Классы массива обрабатываются по-другому от классов немассива и от интерфейсов. Детали процесса разрешения также зависят от того, является ли ссылка, запрашивающая разрешение этого класса или интерфейса, от класса, или взаимодействуйте через интерфейс, который был загружен, используя загрузчик класса (§2.16.2).

name_index элемент a CONSTANT_Class постоянная запись пула является ссылкой на a CONSTANT_Utf8 постоянная запись пула (§4.4.7) для строки UTF-8, которая представляет полностью определенное имя (§2.7.9) класса или интерфейса, который будет разрешен. Какой объект представляется a CONSTANT_Class постоянная запись пула, и как разрешить, что запись, определяется следующим образом:

5.1.1 Текущий Класс или Интерфейс, Не Загруженный Загрузчиком Класса

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

  1. Класс или интерфейс C и его суперклассы сначала загружаются (§2.16.2).
  2. Если класс или интерфейс C еще не был загружен, виртуальная машина Java будет искать файл C.class и попытайтесь загрузить класс или соединить интерфейсом с C от того файла. Отметьте, что нет никакой гарантии что файл C.class будет фактически содержать класс или соединять интерфейсом с C, или что файл C.class даже допустимое class файл. Также возможно, что класс или интерфейс C, возможно, были уже загружены, но еще не инициализированы. Эта фаза загрузки должна обнаружить следующие ошибки:
  3. Если суперкласс загружаемого класса еще не был загружен, это загружается, используя этот шаг 1 рекурсивно. Загрузка суперкласса должна обнаружить любую из ошибок в шаге 1a, где этот суперкласс, как полагают, является загружаемым классом. Отметьте, что все интерфейсы должны иметь java.lang.Object как их суперкласс, который, должно быть, уже был загружен.
  4. Если загрузка класса C и его суперклассов была успешна, суперкласс (и таким образом его суперклассы, если кто-либо) класса C соединяются и инициализируются, применяя шаги-2-4 рекурсивно.
  5. Класс C соединяется (§2.16.3), то есть, это проверяется (§4.9) и готовится.
  6. Во-первых, класс или интерфейс C проверяются, чтобы гарантировать, что его двоичное представление структурно допустимо (передает 2 и 3 из §4.9.1).1 Проверок могут самостоятельно заставить классы и интерфейсы быть загруженными, но не инициализированными (чтобы избежать зацикливания), используя процедуру в шаге 1.
  7. Если class файл для класса или интерфейса C успешно проверяется, класс или интерфейс готовятся. Подготовка включает создание статических полей для класса или интерфейса и инициализации тех полей к их стандартным значениям по умолчанию (§2.5.1). Подготовка не должна быть перепутана с выполнением статических инициализаторов (§2.11); в отличие от выполнения статических инициализаторов, подготовка не требует выполнения любого кода Java. Во время подготовки:
  8. Определенные проверки, которые являются определенными для отдельных инструкций виртуальной машины Java, но которые логически связываются с этой фазой постоянного разрешения пула, описываются в документации тех инструкций. Например, getfield инструкция разрешает свою полевую ссылку, и только позже проверяет, чтобы видеть, является ли то поле полем экземпляра (то есть, это не static). Такие исключения все еще рассматриваются и документируются, чтобы соединиться, не время выполнения, исключения.
  9. Затем, класс инициализируется. Детали процедуры инициализации даются в §2.16.5 и в Спецификации языка Java.
  10. Наконец, права доступа к разрешаемому классу проверяются:
Если ни одна из предыдущих ошибок не была обнаружена, постоянное разрешение пула класса или интерфейсной ссылки, должно быть, завершилось успешно. Однако, если бы ошибка была обнаружена, то одно из следующего должно быть истиной.

Или в случае, сбоях разрешения, и классе или в интерфейсе, пытающемся выполнять разрешение, мешается получить доступ к классу, на который ссылаются, или интерфейсу.

5.1.2 Текущий Класс или Интерфейс, Загруженный Загрузчиком Класса

Если класс или интерфейс, загруженное использование загрузчика класса, ссылаются на класс немассива или интерфейс C, то тот же самый загрузчик класса используется, чтобы загрузить C. loadClass метод того загрузчика класса вызывается на полностью определенный путь (§2.7.9) класса, который будет разрешен. Значение, возвращенное loadClass метод является разрешенным классом. Остаток от раздела описывает этот процесс более подробно.

Каждый загрузчик класса является экземпляром подкласса абстрактного класса ClassLoader. Приложения реализуют подклассы ClassLoader чтобы расширить способ, которым виртуальная машина Java динамически загружает классы. Загрузчики класса могут использоваться, чтобы создать классы, которые происходят из источников кроме файлов. Например, класс мог быть загружен через сеть, он мог быть сгенерирован на лету, или он мог быть дешифрован от скремблированного файла.

Виртуальная машина Java вызывает loadClass метод загрузчика класса, чтобы заставить это загружаться (и дополнительно соединять и инициализировать) класс. Первый параметр loadClass полностью определенное имя класса, который будет загружен. Вторым параметром является булевская переменная. Значение false указывает, что указанный класс должен быть загружен, но не соединен или инициализирован; значение true указывает, что класс должен быть загружен, соединен, и инициализирован.

Реализации загрузчиков класса обязаны отслеживать, из которых классов они уже загрузились, соединились, и initialized:2

Когда загрузчик класса loadClass метод вызывается с именем класса, или соедините интерфейсом с этим, это еще не загрузилось, загрузчик класса должен выполнить одну из следующих двух операций, чтобы загрузить класс или интерфейс:

После того, как класс или интерфейс и его суперклассы были загружены успешно, если второй параметр loadClass true класс или интерфейс соединяются и инициализируются. Этот второй параметр всегда true если загрузчик класса призывается, чтобы разрешить запись в постоянном пуле класса или интерфейса. Загрузчик класса соединяет и инициализирует класс или интерфейс, вызывая метод resolveClass в классе ClassLoader. Соединение и инициализация класса или интерфейса, создаваемого загрузчиком класса, очень подобны соединению и инициализации класса или интерфейса без загрузчика класса (шаги 2-4 §5.1.1):

Во-первых, суперкласс класса или интерфейса соединяется и инициализируется, вызывая loadClass метод загрузчика класса с полностью определенным именем суперкласса как первый параметр, и true как второй параметр. Соединение и инициализация может привести к собственному суперклассу суперкласса, соединяемому и инициализированному. Соединение и инициализация суперкласса должно обнаружить любую из ошибок шага 3 §5.1.1.

Затем, верификатор байт-кода выполняется на классе или соединяемом интерфейсе и инициализируется. Верификатору, возможно, самостоятельно понадобятся классы или интерфейсы, которые будут загружены, и если так, он загружает их, вызывая loadClass метод того же самого загрузчика класса со вторым параметром быть false. Так как проверка может самостоятельно заставить классы или интерфейсы быть загруженными (но не соединенным или инициализированным, избегать зацикливания), это должно обнаружить ошибки шага 1 §5.1.1 для любых классов или взаимодействует через интерфейс, это пытается загрузиться. Выполнение верификатора может также вызвать ошибки шага 3a §5.1.1.

Если файл класса успешно проверяется, класс или интерфейс тогда готовятся (шаг 3b §5.1.1) и инициализируются (шаг 4 §5.1.1).

Наконец, права доступа к классу или интерфейсу проверяются (шаг 5 §5.1.1). Если у текущего класса или интерфейса нет разрешения, чтобы получить доступ к разрешаемому классу, разрешение класса бросает IllegalAccessError исключение.

Если ни одна из предыдущих ошибок не была обнаружена, загрузка, соединение, и инициализация класса или интерфейса, должно быть, завершилась успешно.

5.1.3 Классы массива

Постоянная запись пула, тегированная как CONSTANT_Class (§4.4.1) представляет класс массива если первый символ строки UTF-8 (§4.4.7) ссылаемый name_index элемент той постоянной записи пула является левой скобкой ("["). Число начальных последовательных левых скобок на имя представляет число размерностей класса массива. После того или большего количества начальных последовательных левых скобок полевой дескриптор (§4.3.2) представляющий или тип примитива или ссылочный тип немассива; этот полевой дескриптор представляет базовый тип класса массива.

Следующие шаги выполняются, чтобы разрешить класс массива, на который ссылаются от постоянного пула класса или интерфейса:

  1. Определите число размерностей класса массива и полевого дескриптора, который представляет базовый тип класса массива.
  2. Определите базовый тип класса массива:
  1. Если класс массива, представляющий тот же самый базовый тип и то же самое число размерностей, был уже создан, результатом разрешения является тот класс массива. Иначе, новый класс массива, представляющий обозначенный базовый тип и число размерностей, создается.

5.2 Поле и Разрешение Метода

Постоянная запись пула, тегированная как CONSTANT_Fieldref (§4.4.2) представляет класс или переменную экземпляра (§2.9) или (постоянное) поле интерфейса (§2.13.4). Отметьте, что у интерфейсов нет переменных экземпляра. Постоянная запись пула, тегированная как CONSTANT_Methodref (§4.4.2) представляет метод класса (a static метод) или экземпляра класса (метод экземпляра). Ссылки, чтобы соединить интерфейсом с методами делаются, используя CONSTANT_InterfaceMethodref постоянные записи пула; разрешение таких записей описывается в §5.3.

Разрешить полевую ссылку или ссылку метода, CONSTANT_Class (§4.4.1) запись, представляющая класс, которого поле или метод являются элементом, должен сначала быть успешно разрешен (§5.1). Таким образом, любое исключение, которое может быть выдано, решая a CONSTANT_Class постоянная запись пула может также быть брошена в результате разрешения a CONSTANT_Fieldref или CONSTANT_Methodref запись. Если CONSTANT_Class запись, представляющая класс или интерфейс, может быть успешно разрешена, исключения, касающиеся соединения метода или самого поля, могут быть выданы. Разрешая полевую ссылку:

Разрешая метод:


5.3 Интерфейсное Разрешение Метода

Постоянная запись пула, тегированная как CONSTANT_InterfaceMethodref (§4.4.2) представляет звонок в метод экземпляра, объявленный интерфейсом. Такая постоянная запись пула разрешается, преобразовывая это в машинно-зависимый внутренний формат. Никакая ошибка или исключение не возможны за исключением задокументированных в §6.3.


5.4 Строковое Разрешение

Постоянная запись пула, тегированная как CONSTANT_String (§4.4.3) представляет экземпляр строкового литерала (§2.3), то есть, литерал встроенного типа java.lang.String. Символы Unicode (§2.1) строкового литерала, представленного CONSTANT_String запись находится в CONSTANT_Utf8 (§4.4.7) постоянная запись пула, что CONSTANT_String ссылки записи.

Язык Java требует, чтобы идентичные строковые литералы (то есть, литералы, которые содержат ту же самую последовательность символов Unicode) сослались на тот же самый экземпляр класса String. Кроме того, если метод intern вызывается на любой строке, результатом является ссылка на тот же самый экземпляр класса, который был бы возвращен, если бы та строка появилась как литерал. Таким образом,

    ("a" + "b" + "c").intern() == "abc"
должен иметь значение true.3

Разрешить постоянную тегированную запись пула CONSTANT_String, виртуальная машина Java исследует серию символов Unicode, представленных строкой UTF-8 что CONSTANT_String ссылки записи.

Никакая ошибка или исключение не возможны во время строкового разрешения за исключением задокументированных в §6.3.


5.5 Разрешение Других Постоянных Элементов Пула

Постоянные записи пула, которые тегируются CONSTANT_Integer или CONSTANT_Float (§4.4.4), CONSTANT_Long или CONSTANT_Double (§4.4.5) у всех есть значения, которые непосредственно представляются в пределах постоянного пула. Их разрешение не может выдать исключения за исключением задокументированных в §6.3.

Постоянные записи пула, которые тегируются CONSTANT_NameAndType (§4.4.6), и CONSTANT_Utf8 (§4.4.7) никогда не разрешаются непосредственно. На них только ссылаются прямо или косвенно другие постоянные записи пула.


Выпуск 1.0.2 JDK 1 Sun только проверяет class файлы, у которых есть загрузчики класса; это принимает это class файлам, загруженным локально, доверяют и не нуждаются в проверке.

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

3 разрешения Строкового литерала не реализуются правильно в выпуске 1.0.2 JDK Sun. В той реализации виртуальной машины Java, решая a CONSTANT_String в постоянном пуле всегда выделяет новую строку. Два строковых литерала в двух различных классах, даже если бы они содержали идентичную последовательность символов, никогда не были бы == друг другу. Строковый литерал никогда не мог быть == к результату intern метод.


Содержание | Предыдущий | Следующий | Индекс

Спецификация Виртуальной машины Java

Авторское право © 1996, 1997 Sun Microsystems, Inc. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления к jvm@java.sun.com

free hit counter