Spec-Zone .ru
спецификации, руководства, описания, API
|
Содержание | Предыдущий | Следующий | Индекс | Спецификация Виртуальной машины JavaTM |
ГЛАВА 5
Виртуальная машина Java динамически загружается (§2.17.2), ссылки (§2.17.3), и инициализирует (§2.17.4) классы и интерфейсы. Загрузка является процессом обнаружения двоичного представления класса или интерфейсного типа с определенным именем и созданием класса или интерфейса от того двоичного представления. Соединение является процессом взятия класса или интерфейса и объединения этого в состояние времени выполнения виртуальной машины Java так, чтобы это могло быть выполнено. Инициализация класса или интерфейса состоит из выполнения класса или интерфейсного метода инициализации <clinit>
(§3.9).
В этой главе Раздел 5.1 описывает, как виртуальная машина Java получает символьные ссылки из двоичного представления класса или интерфейса. Раздел 5.2 объясняет, как процессы загрузки, соединения, и инициализации сначала инициируются виртуальной машиной Java. Раздел 5.3 определяет, как двоичные представления классов и интерфейсов загружаются загрузчиками класса и как создаются классы и интерфейсы. Соединение описывается в Разделе 5.4. Разделите 5.5 деталей, как инициализируются классы и интерфейсы. Наконец, Раздел 5.6 представляет понятие привязки собственных методов.
constant_pool
таблица (§4.4) в двоичном представлении класса или интерфейса используется, чтобы создать пул константы этапа выполнения на класс или интерфейсное создание (§5.3). Все ссылки в пуле константы этапа выполнения являются первоначально символьными. Символьные ссылки в пуле константы этапа выполнения получаются из структур в двоичном представлении класса или интерфейса следующим образом:
CONSTANT_Class_info
структура (§4.4.1) в двоичном представлении класса или интерфейса. Такая ссылка дает имя класса или интерфейса в форме, возвращенной Class.getName
метод, который является:
Class.getName
метод.
CONSTANT_Fieldref_info
структура (§4.4.2) в двоичном представлении класса или интерфейса. Такая ссылка дает имя и дескриптор поля, так же как символьную ссылку на класс или интерфейс, в котором должно быть найдено поле.
CONSTANT_Methodref_info
структура (§4.4.2) в двоичном представлении класса или интерфейса. Такая ссылка дает имя и дескриптор метода, так же как символьную ссылку на класс, в котором должен быть найден метод.
CONSTANT_InterfaceMethodref_info
структура (§4.4.2) в двоичном представлении класса или интерфейса. Такая ссылка дает имя и дескриптор интерфейсного метода, так же как символьную ссылку на интерфейс, в котором должен быть найден метод. constant_pool
таблица:
CONSTANT_String_info
структура (§4.4.3) в двоичном представлении класса или интерфейса. CONSTANT_String_info
структура дает последовательность символов Unicode, составляющих строковый литерал.
String
. Кроме того, если метод String.intern
вызывается на любой строке, результатом является ссылка на тот же самый экземпляр класса, который был бы возвращен, если бы та строка появилась как литерал. Таким образом, должен иметь значение(
"a
" + "b
" + "c
").intern()
== "abc
"
true
.
CONSTANT_String_info
структура.
String.intern
был ранее вызван на экземпляре класса String
содержа последовательность символов Unicode, идентичных данному CONSTANT_String_info
структура, тогда результатом деривации строкового литерала является ссылка на тот же самый экземпляр класса String
.
String
создается содержащий последовательность символов Unicode, данных CONSTANT_String_info
структура; тот экземпляр класса является результатом деривации строкового литерала. Наконец, intern
метод нового String
экземпляр вызывается.
CONSTANT_Integer_info
, CONSTANT_Float_info
, CONSTANT_Long_info
, или CONSTANT_Double_info
структуры (§4.4.4, §4.4.5) в двоичном представлении класса или интерфейса. Отметьте это CONSTANT_Float_info
структуры представляют значения в IEEE 754 единственный формат и CONSTANT_Double_info
структуры представляют значения в IEEE 754 двойной формат (§4.4.4, §4.4.5). Ставки константы этапа выполнения, сделанные на эти структуры, должны таким образом быть значениями, которые могут быть представлены, используя IEEE 754 единственные и двойные форматы, соответственно. constant_pool
таблица двоичного представления класса или интерфейса, CONSTANT_NameAndType_info
(§4.4.6) и CONSTANT_Utf8_info
(§4.4.7) структуры только используются косвенно, получая символьные ссылки на классы, интерфейсы, методы, и поля, и получая строковые литералы.public
метод класса void
main(String[])
. Вызов этого метода управляет всем дальнейшим выполнением. Выполнение инструкций виртуальной машины Java, составляющих main
метод может вызвать соединение (и следовательно создание) дополнительных классов и интерфейсов, так же как вызова дополнительных методов. В некоторых реализациях виртуальной машины Java начальный класс мог быть обеспечен как параметр командной строки, как в выпусках 1.0 и 1.1 JDK. Альтернативно, начальный класс мог быть обеспечен реализацией. В этом случае начальный класс мог бы установить загрузчик класса, который поочередно загрузит приложение, как в Java 2 SDK, Standard Edition, v1.2. Другие варианты начального класса возможны, пока они являются непротиворечивыми со спецификацией, данной в предыдущем абзаце.
Если C не является классом массива, он создается, загружая двоичное представление C (см. Главу 4, "Формат файла класса"), использование загрузчика класса (§2.17.2). У классов массива нет внешнего двоичного представления; они создаются виртуальной машиной Java, а не загрузчиком класса.
Есть два типа загрузчиков класса: определяемые пользователем загрузчики класса и загрузчик класса начальной загрузки предоставляются виртуальной машиной Java. Каждый определяемый пользователем загрузчик класса является экземпляром подкласса абстрактного класса ClassLoader
. Приложения используют загрузчики класса, чтобы расширить способ, которым виртуальная машина Java динамически загружает и таким образом создает классы. Определяемые пользователем загрузчики класса могут использоваться, чтобы создать классы, которые происходят из определяемых пользователем источников. Например, класс мог быть загружен через сеть, генерировал на лету, или извлек из зашифрованного файла.
Загрузчик класса L может создать C, определяя это непосредственно или делегируя к другому загрузчику класса. Если L создает C непосредственно, мы говорим, что L определяет C или, эквивалентно, что L является загрузчиком определения C.
Когда один загрузчик класса делегирует к другому загрузчику класса, загрузчик, который инициирует загрузку, является не обязательно тем же самым загрузчиком, который завершает загрузку и определяет класс. Если L создает C, или определяя это непосредственно или делегацией, мы говорим, что загрузка новичков L C или, эквивалентно, что L является загрузчиком инициирования C.
Во время выполнения, класс или интерфейс определяется не одним только его именем, а парой: его полностью определенное имя и его загрузчик класса определения. Каждый такой класс или интерфейс принадлежат единственному пакету времени выполнения. Пакет времени выполнения класса или интерфейса определяется именем пакета и загрузчиком класса определения класса или интерфейса.
Виртуальная машина Java использует одну из трех процедур, чтобы создать класс или соединить интерфейсом с C, обозначенным N:
Во-первых, виртуальная машина Java определяет, был ли загрузчик класса начальной загрузки уже записан как загрузчик инициирования класса или интерфейса, обозначенного N. Если так, этот класс или интерфейс являются C, и никакое создание класса не необходимо.
Иначе, виртуальная машина Java выполняет одну из следующих двух операций, чтобы загрузить C:
Как правило, класс или интерфейс будут представлены, используя файл в иерархической файловой системе. Имя класса или интерфейса будет обычно кодироваться в пути файла.
Эта фаза загрузки должна обнаружить следующую ошибку:
NoClassDefFoundError
или экземпляр одного из его подклассов. Затем виртуальная машина Java пытается получить класс, обозначенный N использование загрузчика класса начальной загрузки от подразумеваемого представления, используя алгоритм, найденный в Разделе 5.3.5. Тот класс является C.
loadClass
метод на L. Результатом вызова является C. Виртуальная машина Java тогда записывает это, программа начальной загрузки является загрузчиком инициирования C (§5.3.4). Во-первых, виртуальная машина Java определяет, был ли L уже записан как загрузчик инициирования класса или интерфейса, обозначенного N. Если так, этот класс или интерфейс являются C, и никакое создание класса не необходимо.
Иначе виртуальная машина Java вызывает loadClass(
N )
на L.1 значение, возвращенное вызовом, является создаваемым классом или интерфейсом C. Виртуальная машина Java тогда записывает это, L является загрузчиком инициирования C (§5.3.4). Остаток от этого раздела описывает этот процесс более подробно.
Когда loadClass
метод загрузчика класса L вызывается с именем N класса, или интерфейс C, чтобы быть загруженным, L должен выполнить одну из следующих двух операций, чтобы загрузить C:
ClassFile
структура (§4.1); это тогда должно вызвать метод defineClass
из класса ClassLoader
. Вызов defineClass
заставляет виртуальную машину Java получать класс или интерфейс, обозначенный N, использующим L от массива байтов, используя алгоритм, найденный в Разделе 5.3.5.loadClass
метод). Результатом вызова является C. Если L был уже записан как загрузчик инициирования класса массива с тем же самым компонентным типом как N, тот класс является C, и никакое создание класса массива не необходимо. Иначе, следующие шаги выполняются, чтобы создать C:
public
. Когда класс или интерфейс C = <N1, L1> делает символьную ссылку на поле или метод другого класса или интерфейса D = <N2, L2>, символьная ссылка включает дескриптор, определяющий тип поля, или возврат и типы параметра метода. Важно, что любое имя типа N упомянутый в поле или дескрипторе метода обозначает тот же самый класс или интерфейс когда загружено L1 и когда загружено L2.
Чтобы гарантировать это, виртуальная машина Java налагает загружающиеся ограничения формы NL1 = NL2 во время подготовки (§5.4.2) и разрешение (§5.4.3). Чтобы осуществить эти ограничения, виртуальная машина Java будет в определенные предписанные времена (см. §5.3.1, §5.3.2, §5.3.3, и §5.3.5), запись, что определенный загрузчик является загрузчиком инициирования определенного класса. После записи, что загрузчик является загрузчиком инициирования класса, виртуальная машина Java должна сразу проверить, чтобы видеть, нарушаются ли какие-либо ограничения загрузки. Если так, от записи отрекаются, виртуальная машина Java бросает a LinkageError
, и загружающаяся работа, которая заставила запись иметь место сбои.
Точно так же после наложения загружающегося ограничения (см. §5.4.2, §5.4.3.2, §5.4.3.3, и §5.4.3.4), виртуальная машина Java должна сразу проверить, чтобы видеть, нарушаются ли какие-либо ограничения загрузки. Если так, от недавно наложенного ограничения загрузки отрекаются, виртуальная машина Java бросает a LinkageError
, и работа, которая заставила ограничение быть наложенным (или разрешение или подготовка, в зависимости от обстоятельств) сбои.
Ситуации, описанные здесь, являются единственными временами, в которые виртуальная машина Java проверяет, были ли какие-либо ограничения загрузки нарушены. Загружающееся ограничение нарушается, если, и только если, все следующие четыре условия содержат:
class
Представление файлаclass
формат файла. LinkageError
.Эта фаза загрузки должна обнаружить следующие ошибки:
class
формат файла (§4.1, передайте 1 из §4.9.1), загружая броски экземпляр ClassFormatError
.
UnsupportedClassVersionError
.2
NoClassDefFoundError
или экземпляр одного из его подклассов. Object
как его прямой суперкласс, который, должно быть, уже был загружен. Только Object
не имеет никакого прямого суперкласса. Любые исключения, которые могут быть брошены из-за класса или интерфейсного разрешения, могут быть выданы в результате этой фазы загрузки. Кроме того, эта фаза загрузки должна обнаружить следующие ошибки:
IncompatibleClassChangeError
.
ClassCircularityError
. Любые исключения, которые могут быть брошены из-за класса или интерфейсного разрешения, могут быть выданы в результате этой фазы загрузки. Кроме того, эта фаза загрузки должна обнаружить следующие ошибки:
IncompatibleClassChangeError
.
ClassCircularityError
. Проверка должна обнаружить следующую ошибку:
VerifyError
. Во время подготовки класса или интерфейса C, виртуальная машина Java также налагает загружающиеся ограничения (§5.3.4). Позвольте L1 быть загрузчиком определения C. Для каждого метода м. объявил в C, который переопределяет метод, объявленный в суперклассе или суперинтерфейсе
Подготовка может произойти в любое время после создания, но должна быть завершена до инициализации. Разрешение может быть предпринято на символьной ссылке, которая была уже разрешена. Попытка разрешить символьную ссылку, которая была уже успешно разрешена всегда, успешно выполняется тривиально и всегда приводит к тому же самому объекту, произведенному начальным разрешением той ссылки.
Последующие попытки разрешить символьную ссылку, что виртуальная машина Java ранее неудачно попыталась разрешить всегда сбои с той же самой ошибкой, которая была брошена в результате начальной попытки разрешения.
Определенные инструкции виртуальной машины Java требуют определенных проверок соединения, разрешая символьные ссылки. Например, для getfield инструкции, чтобы успешно разрешить символьную ссылку на поле, на котором это работает, это должно завершить полевые шаги разрешения, данные в Разделе 5.4.3.2. Кроме того, это должно также проверить, что поле не
Соединение исключений, сгенерированных проверками, которые являются определенными для выполнения определенной инструкции виртуальной машины Java, дается в описании той инструкции и не покрывается этим общим обсуждением разрешения. Отметьте, что такие исключения, хотя описано как часть выполнения инструкций виртуальной машины Java, а не разрешения, все еще должным образом считают отказом разрешения.
Инструкции виртуальной машины Java anewarray, checkcast, getfield, getstatic, instanceof, invokeinterface, invokespecial, invokestatic, invokevirtual, multianewarray, новый, putfield, и putstatic делают символьные ссылки на пул константы этапа выполнения. Выполнение любой из этих инструкций требует разрешения своей символьной ссылки.
Следующие разделы описывают процесс разрешения символьной ссылки в пуле константы этапа выполнения (§5.1) класса или взаимодействуют через интерфейс, Д. Детэйлс разрешения не соглашаются с видом символьной ссылки, которая будет разрешена.
Это условие может произойти, например, если C является классом, который, как первоначально объявляли, был Разрешая полевую ссылку, полевое разрешение сначала пытается искать поле, на которое ссылаются, в C и его суперклассах:
Иначе, позвольте <E, L1> быть классом или интерфейсом, в котором поле, на которое ссылаются, фактически объявляется и позволяется L2 быть загрузчиком определения D. Позвольте T быть именем типа поля, на которое ссылаются. Виртуальная машина Java должна наложить загружающееся ограничение это TL1=TL2 (§5.3.4).
Иначе, позвольте <E, L1> быть классом или интерфейсом, в котором метод, на который ссылаются, фактически объявляется и позволяется L2 быть загрузчиком определения D. Позвольте T0 быть именем типа, возвращенного методом, на который ссылаются, и позволять T1..., Tn быть именами типов параметра метода, на который ссылаются. Виртуальная машина Java должна наложить загружающиеся ограничения TiL1=TiL2 поскольку я = 0 к n (§5.3.4). Разрешая интерфейсную ссылку метода:
Класс или интерфейс могут быть инициализированы только в результате:
2
Содержание | Предыдущий | Следующий | Индекс
Спецификация Виртуальной машины JavaTM 5.4.3 Разрешение
Процесс динамичного определения конкретных значений из символьных ссылок в пуле константы этапа выполнения известен как разрешение. static
. Если это - a static
поле, соединяющееся исключение должно быть выдано. 5.4.3.1 Класс и Интерфейсное Разрешение
Чтобы разрешить неразрешенную символьную ссылку от D до класса или соединить интерфейсом с C, обозначенным N, следующие шаги выполняются:
Если шаги 1 и 2 успешно выполняются, но сбои шага 3, C все еще допустим и применим. Однако, сбоям разрешения, и D мешают получить доступ к C. IllegalAccessError
. public
но был изменен, чтобы быть не -public
после того, как D был скомпилирован. 5.4.3.2 Полевое Разрешение
Чтобы разрешить неразрешенную символьную ссылку от D до поля в классе или соединить интерфейсом с C, символьная ссылка на C, данный полевой ссылкой, должна сначала быть разрешена (§5.4.3.1). Поэтому, любое исключение, которое может быть брошено в результате отказа разрешения класса или интерфейсной ссылки, может быть выдано в результате отказа полевого разрешения. Если ссылка на C может быть успешно разрешена, исключение, касающееся отказа разрешения самой полевой ссылки, может быть выдано.
Если полевой поиск перестал работать, полевое разрешение бросает a NoSuchFieldError
. Иначе, если полевой поиск успешно выполняется, но поле, на которое ссылаются, не доступно (§5.4.4) для D, полевое разрешение бросает IllegalAccessError
.5.4.3.3 Разрешение метода
Чтобы разрешить неразрешенную символьную ссылку от D до метода в классе C, символьная ссылка на C, данный ссылкой метода, сначала разрешается (§5.4.3.1). Поэтому, любые исключения, которые могут быть брошены из-за разрешения ссылки класса, могут быть выданы в результате разрешения метода. Если ссылка на C может быть успешно разрешена, исключения, касающиеся разрешения ссылки самого метода, могут быть выданы.
Если поиск метода перестал работать, разрешение метода бросает a IncompatibleClassChangeError
. NoSuchMethodError
. Если поиск метода успешно выполняется, и метод abstract
, но C не abstract
, разрешение метода бросает AbstractMethodError
. Иначе, если метод, на который ссылаются, не доступен (§5.4.4) для D, разрешение метода бросает IllegalAccessError
.5.4.3.4 Интерфейсное Разрешение Метода
Чтобы разрешить неразрешенную символьную ссылку от D до интерфейсного метода в интерфейсе C, символьная ссылка на C, данный интерфейсной ссылкой метода, сначала разрешается (§5.4.3.1). Поэтому, любые исключения, которые могут быть брошены в результате отказа разрешения интерфейсной ссылки, могут быть выданы в результате отказа интерфейсного разрешения метода. Если ссылка на C может быть успешно разрешена, исключения, касающиеся разрешения интерфейсной ссылки метода, могут быть выданы.
Иначе, позвольте <E, L1> быть интерфейсом, в котором интерфейсный метод, на который ссылаются, фактически объявляется и позволяется L2 быть загрузчиком определения D. Позвольте T0 быть именем типа, возвращенного методом, на который ссылаются, и позволять T1..., Tn быть именами типов параметра метода, на который ссылаются. Виртуальная машина Java должна наложить загружающиеся ограничения TiL1 = TiL2 поскольку я = 0 к n (§5.3.4).IncompatibleClassChangeError
.Object
, интерфейсное разрешение метода бросает a NoSuchMethodError
. 5.4.4 Управление доступом
Класс или интерфейс C доступны для класса или интерфейса D, если и только если любое из следующих условий является истиной:
Поле или метод R доступны для класса или интерфейса D, если и только если любое из следующих условий является истиной: public
.
Это обсуждение управления доступом опускает связанное ограничение на цель a public
.protected
и объявляется в классе C, и D является или подклассом C или C непосредственно.protected
или частный пакет (то есть, ни один public
ни protected
ни private
), и объявляется классом в том же самом пакете времени выполнения как D.private
и объявляется в D. protected
доступ к полю или вызов метода (цель должна иметь класс D или подтип D). То требование проверяется как часть процесса проверки (§5.4.1); это не часть разового ссылкой управления доступом.5.5 Инициализация
Инициализация класса или интерфейса состоит из вызова его статических инициализаторов (§2.11) и инициализаторов для статических полей (§2.9.2) объявленный в классе. Этот процесс описывается более подробно в §2.17.4 и §2.17.5.
До инициализации класс или интерфейс должны быть соединены, то есть, проверены, подготовлены, и дополнительно разрешены. Class
или в пакете java.lang.reflect
. 5.6 Привязка Собственных Реализаций Метода
Привязка является процессом который функция, записанная на языке кроме языка программирования Java и реализующий a native
метод интегрируется в виртуальную машину Java так, чтобы это могло быть выполнено. Хотя этот процесс традиционно упоминается как соединение, термин привязка используется в спецификации, чтобы избежать беспорядка с соединением классов или интерфейсов виртуальной машиной Java.
1 Начиная с выпуска 1.1 JDK виртуальная машина Java вызывает loadClass
метод загрузчика класса, чтобы заставить это загружать класс или интерфейс. Параметр loadClass
имя класса или интерфейса, который будет загружен. Есть также версия с двумя параметрами loadClass
метод. Вторым параметром является a boolean
это указывает, должны ли класс или интерфейс быть соединены или нет. Только версия с двумя параметрами была предоставлена в выпуске 1.0.2 JDK, и виртуальной машине Java, на которую полагаются это, чтобы соединить загруженный класс или интерфейс. От выпуска 1.1 JDK вперед, виртуальная машина Java соединяет класс, или взаимодействуйте через интерфейс непосредственно, не полагаясь на загрузчик класса.UnsupportedClassVersionError
был представлен в Java 2 платформы, Standard Edition, v1.2. В более ранних версиях платформы экземпляр NoClassDefFoundError
или ClassFormatError
был брошен в случае неподдерживаемой версии в зависимости от того, загружался ли класс системным загрузчиком класса или определяемым пользователем загрузчиком класса.
Авторское право © Sun Microsystems, Inc 1999 года. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления к jvm@java.sun.com