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
может быть брошен в любое время во время постоянного разрешения пула.
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.3).
еще не был загружен, виртуальная машина Java будет искать файл C.class
и попытайтесь загрузить класс или соединить интерфейсом с C от того файла. Отметьте, что нет никакой гарантии что файл C.class
будет фактически содержать класс или соединять интерфейсом с C, или что файл C.class
даже допустимое class
файл. Также возможно, что класс или интерфейс C, возможно, были уже загружены, но еще не инициализированы. Эта фаза загрузки должна обнаружить следующие ошибки: NoClassDefFoundError
.
class
файл (передают 1 из §4.9.1), или не является a class
файл поддерживаемой основной или вспомогательной версии (§4.1), класс или интерфейсное разрешение бросает a NoClassDefFoundError
.
class
файл фактически не содержал требуемый класс или интерфейс, класс или соединял интерфейсом с бросками разрешения a NoClassDefFoundError
.
class
файл не определяет суперкласс и не class
файл для класса Object
, класс или интерфейсное разрешение бросают a ClassFormat-Error
. java.lang.Object
как их суперкласс, который, должно быть, уже был загружен.
class
файл C.class
не удовлетворяет статические или структурные ограничения на допустимый class
файлы, перечисленные в Разделе 4.8, "Ограничения на Код виртуальной машины Java," класс или интерфейсное разрешение бросают a VerifyError
. class
файл для класса или интерфейса C успешно проверяется, класс или интерфейс готовятся. Подготовка включает создание статических полей для класса или интерфейса и инициализации тех полей к их стандартным значениям по умолчанию (§2.5.1). Подготовка не должна быть перепутана с выполнением статических инициализаторов (§2.11); в отличие от выполнения статических инициализаторов, подготовка не требует выполнения любого кода Java. Во время подготовки: abstract
имеет abstract
метод, разрешение класса бросает AbstractMethodError
. static
). Такие исключения все еще рассматриваются и документируются, чтобы соединиться, не время выполнения, исключения.
Error
или один из его подклассов, затем новый экземпляр класса ExceptionInInitializerError
, с E, поскольку параметр, создается и используется вместо E.
ExceptionInInitializerError
но неспособно сделать так потому что Out-Of--Memory-Error
происходит, тогда OutOfMemoryError
объект бросается вместо этого. Illegal-Access-Error
. Это условие может произойти, например, если класс, который первоначально объявляется public
изменяется, чтобы быть private
после того, как другой класс, который обращается к классу, был скомпилирован.
loadClass
метод того загрузчика класса вызывается на полностью определенный путь (§2.7.9) класса, который будет разрешен. Значение, возвращенное loadClass
метод является разрешенным классом. Остаток от раздела описывает этот процесс более подробно. Каждый загрузчик класса является экземпляром подкласса абстрактного класса ClassLoader
. Приложения реализуют подклассы ClassLoader
чтобы расширить способ, которым виртуальная машина Java динамически загружает классы. Загрузчики класса могут использоваться, чтобы создать классы, которые происходят из источников кроме файлов. Например, класс мог быть загружен через сеть, он мог быть сгенерирован на лету, или он мог быть дешифрован от скремблированного файла.
Виртуальная машина Java вызывает loadClass
метод загрузчика класса, чтобы заставить это загружаться (и дополнительно соединять и инициализировать) класс. Первый параметр loadClass
полностью определенное имя класса, который будет загружен. Вторым параметром является булевская переменная. Значение false
указывает, что указанный класс должен быть загружен, но не соединен или инициализирован; значение true
указывает, что класс должен быть загружен, соединен, и инициализирован.
Реализации загрузчиков класса обязаны отслеживать, из которых классов они уже загрузились, соединились, и initialized:2
loadClass
метод вызывается с именем класса, или соедините интерфейсом с этим, это еще не загрузилось, загрузчик класса должен выполнить одну из следующих двух операций, чтобы загрузить класс или интерфейс:
class
формат файла; это тогда должно вызвать метод defineClass
из класса ClassLoader
на тех байтах, чтобы преобразовать их в класс или интерфейс с этим загрузчиком класса как загрузчик класса для недавно определенного класса. Вызов define-Class
заставляет виртуальную машину Java выполнять шаг 1a §5.1.1.
defineClass
тогда причины loadClass
метод загрузчика класса, который будет вызван рекурсивно, чтобы загрузить суперкласс недавно определенного класса или интерфейса. Полностью определенный путь суперкласса получается из super_class
элемент в class
формат файла. Когда суперкласс загружается в, второй параметр loadClass
false
, указание, что суперкласс не должен быть соединен и сразу инициализирован.
findSystemClass
в классе ClassLoader
с полностью определенным именем класса или интерфейса, который будет загружен. Вызов этого метода заставляет виртуальную машину Java выполнять шаг 1 §5.1.1. Получающееся class
файл не отмечается как загруженный загрузчиком класса. 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
исключение.
Если ни одна из предыдущих ошибок не была обнаружена, загрузка, соединение, и инициализация класса или интерфейса, должно быть, завершилась успешно.
CONSTANT_Class
(§4.4.1) представляет класс массива если первый символ строки UTF-8 (§4.4.7) ссылаемый name_index
элемент той постоянной записи пула является левой скобкой ("[
"). Число начальных последовательных левых скобок на имя представляет число размерностей класса массива. После того или большего количества начальных последовательных левых скобок полевой дескриптор (§4.3.2) представляющий или тип примитива или ссылочный тип немассива; этот полевой дескриптор представляет базовый тип класса массива. Следующие шаги выполняются, чтобы разрешить класс массива, на который ссылаются от постоянного пула класса или интерфейса:
L
"), тот тип примитива является базовым типом класса массива.
L
"), тот ссылочный тип является базовым типом класса массива. Ссылочный тип самостоятельно разрешается, используя процедуры, обозначенные выше в §5.1.1 или в §5.1.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
запись, представляющая класс или интерфейс, может быть успешно разрешена, исключения, касающиеся соединения метода или самого поля, могут быть выданы. Разрешая полевую ссылку:
NoSuchFieldError
.
IllegalAccessError
исключение. NoSuchMethodError
.
IllegalAccessError
исключение. CONSTANT_InterfaceMethodref
(§4.4.2) представляет звонок в метод экземпляра, объявленный интерфейсом. Такая постоянная запись пула разрешается, преобразовывая это в машинно-зависимый внутренний формат. Никакая ошибка или исключение не возможны за исключением задокументированных в §6.3. 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
ссылки записи.
CONSTANT_String
и представление идентичной последовательности символов Unicode было уже разрешено, тогда результатом разрешения является ссылка на экземпляр класса String
создаваемый для той более ранней постоянной записи пула.
intern
был ранее вызван на экземпляре класса String
содержа последовательность символов Unicode, идентичных представленному постоянной записью пула, тогда, результатом разрешения является ссылка на тот же самый экземпляр класса String
.
String
создается содержащий последовательность символов Unicode, представленных CONSTANT_String
запись; тот экземпляр класса является результатом разрешения. 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) никогда не разрешаются непосредственно. На них только ссылаются прямо или косвенно другие постоянные записи пула.
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