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


ГЛАВА 3

Структура виртуальной машины Java


Эта книга определяет абстрактную машину. Это не документирует определенной реализации виртуальной машины Java, включая Sun Microsystems.

Чтобы реализовать виртуальную машину Java правильно, Вы должны только быть в состоянии читать class формат файла и правильно выполняет операции, определенные там. Детали реализации, которые не являются частью спецификации виртуальной машины Java, излишне ограничили бы творческий потенциал конструкторов. Например, расположение памяти областей данных времени выполнения, алгоритм сборки "мусора", используемый, и любая внутренняя оптимизация инструкций виртуальной машины Java (например, преобразовывая их в машинный код), оставляют усмотрению конструктора.


3.1 class Формат файла

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

Глава 4," class Формат файла", покрытия class формат файла подробно.


3.2 Типы данных

Как язык программирования Java, виртуальная машина Java работает на двух видах типов: типы примитивов и ссылочные типы. Есть, соответственно, два вида значений, которые могут быть сохранены в переменных, передали как параметры, возвращенные методами, и работали на: примитивные значения и ссылочные значения.

Виртуальная машина Java ожидает, что почти вся проверка типа делается до времени выполнения, обычно компилятором, и не должна быть сделана виртуальной машиной Java непосредственно. Значения типов примитивов не должны быть тегированы или иначе быть inspectable, чтобы определить их типы во время выполнения, или быть отличенными от значений ссылочных типов. Вместо этого набор команд виртуальной машины Java отличает свои инструкции использования типов операнда, предназначенные, чтобы работать на значениях определенных типов. Например, iadd, ladd, fadd, и dadd являются всеми инструкциями виртуальной машины Java, которые добавляют два числовых значения и приводят к числовым результатам, но каждый специализируется для ее типа операнда: int, long, float, и double, соответственно. Для сводки поддержки типа в наборе команд виртуальной машины Java см. §3.11.1.

Виртуальная машина Java содержит явную поддержку объектов. Объект является или динамически выделенным экземпляром класса или массивом. У ссылки на объект, как полагают, есть тип виртуальной машины Java reference. Значения типа reference может считаться указателями на объекты. Больше чем одна ссылка на объект может существовать. На объектах всегда управляют, передаются, и тестируются через значения типа reference.


3.3 Типы примитивов и Значения

Примитивные типы данных, поддерживаемые виртуальной машиной Java, являются числовыми типами, boolean введите (§3.3.4), 1 и returnAddress введите (§3.3.3). Числовые типы состоят из целочисленных типов (§3.3.1) и типы с плавающей точкой (§3.3.2). Целочисленные типы:

Типы с плавающей точкой:

Значения boolean тип кодирует значения истинности true и false.

Значения returnAddress тип является указателями на коды операций инструкций виртуальной машины Java. Из типов примитивов только returnAddress тип непосредственно не связывается с типом языка программирования Java.

3.3.1 Целочисленные типы и Значения

Значения целочисленных типов виртуальной машины Java являются тем же самым как теми для целочисленных типов языка программирования Java (§2.4.1):

3.3.2 Типы с плавающей точкой, Наборы значений, и Значения

Типы с плавающей точкой float и double, которые концептуально связываются с 32-разрядной одинарной точностью и 64-разрядными значениями формата IEEE 754 двойной точности и операциями как определено в Стандарте IEEE для Двоичной Арифметики С плавающей точкой, Станд. ANSI/IEEE 754-1985 (IEEE, Нью-Йорк).

Стандарт IEEE 754 включает не только положительный и числа величины знака минус, но также и положительные и отрицательные нули, положительные и отрицательные бесконечности, и специальное значение Не-числа (после этого сокращенный как "НЭН"). Значение НЭН используется, чтобы представить результат определенных недопустимых операций, таких как делящийся нуль нулем.

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

Конечные ненулевые значения любого набора значений с плавающей точкой могут все быть выражены в форме s · м. · 2 (e-N + 1), где s +1 или-1, м. является положительным целым числом меньше чем 2N, и e является целым числом между Эмином = - (2 K-1-2) и Emax = 2 K-1-1, включительно, и где N и K являются параметрами, которые зависят от набора значений. Некоторые значения могут быть представлены в этой форме больше чем одним способом; например, если значение v в наборе значений могло бы быть представлено в этой форме, используя определенные значения для s, м., и e, затем если бы это произошло, которым м. был даже, и e составляли меньше чем 2 k-1, то можно было разделить на два м. и увеличить e на 1, чтобы произвести второе представление для того же самого значения v. Представление в этой форме вызывают нормализованное если м. 2N-1; иначе представление, как говорят, денормализовывается. Если значение в наборе значений не может быть представлено таким способом, которым м. 2N-1, то значение, как говорят, является денормализованным значением, потому что у этого нет никакого нормализованного представления.

Ограничения на параметры N и K (и на полученные параметры Эмин и Эмэкс) для этих требуемых двух и два дополнительных набора значений с плавающей точкой получаются в итоге в Таблице 3.1.

Параметр плавание расширенный до плавания - экспонента двойной двойным образом расширенный - экспонента
N 24 24 53 53
K 8 11 11 15
Emax +127 +1023 +1023 +16383
Эмин -126 -1022 -1022 -16382


Где один или оба набора значений расширенной экспоненты поддерживаются реализацией, затем для каждого поддерживаемого набора значений расширенной экспоненты есть определенный зависящий от реализации постоянный K, значение которого ограничивается Таблицей 3.1; это значение K поочередно диктует значения для Эмина и Эмэкса.

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

Отметьте, что ограничения в Таблице 3.1 разрабатываются так, чтобы каждый элемент набора значений плавающего был обязательно также элементом набора значений "расширенная экспонента плавающая", двойной набор значений, и набор значений "двойная расширенная экспонента". Аналогично, каждый элемент двойного набора значений является обязательно также элементом набора значений "двойная расширенная экспонента". Каждый набор значений расширенной экспоненты имеет больший диапазон значений экспоненты чем соответствующий стандартный набор значений, но не имеет большей точности.

Элементы набора значений плавающего являются точно значениями, которые могут быть представлены, используя единственный формат с плавающей точкой, определенный в стандарте IEEE 754, за исключением того, что есть только одно значение НЭН (IEEE 754 определяет 224 - 2 отличных значения НЭН). Элементы двойного набора значений являются точно значениями, которые могут быть представлены, используя двойной формат с плавающей точкой, определенный в стандарте IEEE 754, за исключением того, что есть только одно значение НЭН (IEEE 754 определяет 253 - 2 отличных значения НЭН). Отметьте, однако, что элементы "плавания, расширенная экспонента" и наборы значений "двойная расширенная экспонента", определенная здесь, не соответствуют значениям, которые можно быть представлена, используя IEEE 754 единственные расширенные и двойные расширенные форматы, соответственно. Эта спецификация не передает под мандат определенное представление для значений наборов значений с плавающей точкой кроме того, где значения с плавающей точкой должны быть представлены в class формат файла (§4.4.4, §4.4.5).

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

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

Положительный нуль с плавающей точкой и отрицательный нуль с плавающей точкой сравниваются как равный, но есть другие операции, которые могут отличить их; например, деление 1.0 0.0 производит положительную бесконечность, но деление 1.0 -0.0 производит отрицательную бесконечность.

NaNs неупорядочивают, таким образом, у числовых сравнений и тестов для числового равенства есть значение false если или или оба из их операндов НЭН. В частности у теста для числового равенства значения против себя есть значение false если и только если значением является НЭН. У теста для количественного неравенства есть значение true если любым операндом является НЭН.

3.3.3 returnAddress Введите и Оценивает

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

3.3.4 boolean Ввести

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

Виртуальная машина Java действительно непосредственно поддерживает boolean массивы. Его newarray инструкция включает созданию boolean массивы. Массивы типа boolean получаются доступ и изменил использование byte инструкции массива baload и bastore.2

Виртуальная машина Java кодирует boolean компоненты массива, используя 1, чтобы представить true и 0, чтобы представить false. Где язык программирования Java boolean значения отображаются компиляторами на значения типа виртуальной машины Java int, компиляторы должны использовать то же самое кодирование.


3.4 Ссылочные типы и Значения

Есть три вида reference типы: типы классов, типы массива, и интерфейсные типы. Их значения являются ссылками на динамически создаваемые экземпляры класса, массивы, или экземпляры класса или массивы, которые реализуют интерфейсы, соответственно. A reference значение может также быть специальной нулевой ссылкой, ссылкой ни на какой объект, который будет обозначен здесь null. null ссылка первоначально не имеет никакого типа времени выполнения, но может быть брошена к любому типу (§2.4).

Спецификация виртуальной машины Java не передает под мандат конкретное кодирование значения null.


3.5 Области Данных времени выполнения

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

3.5.1 pc Регистр

Виртуальная машина Java может поддерживать много потоков выполнения сразу (§2.19). У каждого потока виртуальной машины Java есть свое собственное pc (счетчик программы) регистр. В любой точке каждый поток виртуальной машины Java выполняет код единственного метода, текущий метод (§3.6) для того потока. Если тот метод не native, pc регистр содержит адрес инструкции виртуальной машины Java, в настоящий момент выполняемой. Если метод, в настоящий момент выполняемый потоком, native, значение виртуальной машины Java pc регистр неопределен. Виртуальная машина Java pc регистр достаточно широк, чтобы содержать a returnAddress или собственный указатель на определенной платформе.

3.5.2 Стеки Виртуальной машины Java

У каждого потока виртуальной машины Java есть частный стек виртуальной машины Java, создаваемый одновременно как поток 3, стек виртуальной машины Java хранит фреймы (§3.6). Стек виртуальной машины Java походит на стек стандартного языка, такого как C: это содержит локальные переменные и частичные результаты, и играет роль в вызове метода и возврате. Поскольку стеком виртуальной машины Java никогда не управляют непосредственно кроме продвинуть и вытолкать фреймы, фреймы могут быть выделенной "кучей". Память для стека виртуальной машины Java не должна быть непрерывной.

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

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

3.5.3 "Куча"

У виртуальной машины Java есть "куча", которая совместно используется среди всех потоков виртуальной машины Java. "Куча" является областью данных времени выполнения, от которой выделяется память для всех экземпляров класса и массивов.

"Куча" создается на запуске виртуальной машины. Хранение "кучи" для объектов исправляется автоматической системой управления хранения (известный как сборщик "мусора"); объекты явно никогда не освобождаются. Виртуальная машина Java не принимает определенного типа автоматической системы управления хранения, и метод управления хранением может быть выбран согласно системным требованиям конструктора. "Куча" может иметь фиксированный размер или может быть расширена как требуется вычислением и может быть законтрактована, если большая "куча" становится ненужной. Память для "кучи" не должна быть непрерывной.

Реализация виртуальной машины Java может предоставить программисту или контролю за работой пользователей свыше начального размера "кучи", так же как, если "куча" может быть динамически расширена или законтрактована, управление максимальным и минимальным размером 5 "кучи"

Следующее исключительное условие связывается с "кучей":

3.5.4 Область метода

У виртуальной машины Java есть область метода, которая совместно используется среди всех потоков виртуальной машины Java. Область метода походит на область хранения для скомпилированного кода стандартного языка или аналогичный "текстовому" сегменту в процессе UNIX. Это хранит структуры на класс, такие как пул константы этапа выполнения, поле и данные метода, и код для методов и конструкторов, включая специальные методы (§3.9) используемый в классе и инициализации экземпляра и интерфейсной инициализации типа.

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

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

Следующее исключительное условие связывается с областью метода:

3.5.5 Пул Константы этапа выполнения

Пул константы этапа выполнения является представлением времени выполнения на интерфейс или на класс constant_pool таблица в a class файл (§4.4). Это содержит несколько видов констант, в пределах от числовых литералов, известных во время компиляции методу и полевым ссылкам, которые должны быть разрешены во время выполнения. Пул константы этапа выполнения служит функции, подобной той из таблицы символов для стандартного языка программирования, хотя это содержит более широкий диапазон данных чем типичная таблица символов.

Каждый пул константы этапа выполнения выделяется от области метода виртуальной машины Java (§3.5.4). Пул константы этапа выполнения для класса или интерфейса создается, когда класс или интерфейс создаются (§5.3) виртуальной машиной Java.

Следующее исключительное условие связывается с конструкцией пула константы этапа выполнения для класса или интерфейса:

См. Главу 5 для информации о конструкции пула константы этапа выполнения.

3.5.6 Собственные Стеки Метода

Реализация виртуальной машины Java может использовать стандартные стеки, в разговорной речи вызванные "C стеки," поддерживать native методы, методы, записанные на языке кроме языка программирования Java. Собственные стеки метода могут также использоваться реализацией интерпретатора для набора команд виртуальной машины Java на языке, таком как реализации К. Джейва виртуэл макхайна, которые не могут загрузиться native методы и которые самостоятельно не полагаются на стандартные стеки, не должны предоставить собственные стеки метода. Если предоставлено, собственные стеки метода обычно выделяются на поток, когда каждый поток создается.

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

Следующие исключительные условия связываются с собственными стеками метода:


3.6 Фреймы

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

Новый фрейм создается каждый раз, когда метод вызывается. Фрейм уничтожается, когда его вызов метода завершается, является ли то завершение нормальным или резким (это выдает непойманное исключение). Фреймы выделяются от стека виртуальной машины Java (§3.5.2) потока, создающего фрейм. У каждого фрейма есть свой собственный массив локальных переменных (§3.6.1), его собственный стек операнда (§3.6.2), и ссылка на пул константы этапа выполнения (§3.5.5) класса текущего метода.

Размеры массива локальной переменной и стека операнда определяются во время компиляции и предоставляются наряду с кодом для метода, связанного с фреймом (§4.7.3). Таким образом размер структуры данных фрейма зависит только от реализации виртуальной машины Java, и память для этих структур может быть выделена одновременно на вызове метода.

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

Фрейм прекращает быть текущим, если его метод вызывает другой метод или если его метод завершается. Когда метод вызывается, новый фрейм создается и становится текущим, когда управление передает новому методу. По возврату метода текущий фрейм пасует назад результат своего вызова метода, если таковые вообще имеются, к предыдущему фрейму. Текущий фрейм тогда отбрасывается, поскольку предыдущий фрейм становится текущим.

Отметьте, что фрейм, создаваемый потоком, локален для того потока и не может быть сослан никаким другим потоком.

3.6.1 Локальные переменные

Каждый фрейм (§3.6) содержит массив переменных, известных как его локальные переменные. Длина массива локальной переменной фрейма определяется во время компиляции и предоставляется в двоичном представлении класса или интерфейса наряду с кодом для метода, связанного с фреймом (§4.7.3).

Единственная локальная переменная может содержать значение типа boolean, byte, char, short, int, float, reference, или returnAddress. Пара локальных переменных может содержать значение типа long или double.

Локальные переменные адресуются, индексируя. Индекс первой локальной переменной является нулем. Целое число, как полагать, быть индексом в массив локальной переменной, если и только если то целое число между нулем и меньше чем размер массива локальной переменной.

Значение типа long или введите double занимает две последовательных локальных переменные. Такое значение может только адресоваться, используя меньший индекс. Например, значение типа double сохраненный в массиве локальной переменной по индексу n фактически занимает локальные переменные с индексами n и n +1; однако, локальная переменная по индексу n +1 не может быть загружена из. Это может быть сохранено в. Однако, выполнение так лишает законной силы содержание локальной переменной n.

Виртуальная машина Java не требует, чтобы n был даже. В интуитивных сроках, значениях типов double и long не должен быть 64-разрядное выровненный в массиве локальных переменных. Конструкторы свободны решить соответствующий способ представить такие значения, используя эти две локальных переменные, зарезервированные для значения.

Виртуальная машина Java использует локальные переменные, чтобы передать параметры вызову метода. На вызове метода класса любые параметры передают в последовательных локальных переменных, запускающихся с локальной переменной 0. На вызове метода экземпляра локальная переменная 0 всегда используется, чтобы передать ссылку на объект, на который вызывается метод экземпляра (this в языке программирования Java). Любые параметры впоследствии передают в последовательных локальных переменных, запускающихся с локальной переменной 1.

3.6.2 Стеки операнда

Каждый фрейм (§3.6) содержит в обратном порядке (LIFO) стек, известный как его стек операнда. Максимальная глубина стека операнда фрейма определяется во время компиляции и предоставляется наряду с кодом для метода, связанного с фреймом (§4.7.3).

Где это является четким контекстом, мы будем иногда обращаться к стеку операнда текущего фрейма как просто стек операнда.

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

Например, iadd инструкция добавляет два int значения вместе. Это требует что int значения, которые будут добавлены быть лучшими двумя значениями стека операнда, продвинутого там предыдущими инструкциями. Оба из int значения выталкиваются от стека операнда. Они добавляются, и их сумма пододвигается обратно на стек операнда. Подвычисления могут быть вложены на стеке операнда, приводящем к значениям, которые могут использоваться вычислением затрагивания.

Каждая запись на стеке операнда может содержать значение любого типа виртуальной машины Java, включая значение типа long или введите double.

На значения от стека операнда нужно управлять способами, соответствующими их типам. Не возможно, например, продвинуть два int значения и впоследствии обрабатывают их как a long или продвигать два float значения и впоследствии добавляют их с iadd инструкцией. Небольшое количество инструкций виртуальной машины Java (инструкции дубликата и подкачка) работает на областях данных времени выполнения, поскольку сырые данные оценивают без отношения их определенным типам; эти инструкции определяются таким способом, которым они не могут использоваться, чтобы изменить или разбить отдельные значения. Эти ограничения на манипулирование стеком операнда осуществляются через class проверка файла (§4.9).

В любом моменте времени у стека операнда есть связанная глубина, где значение типа long или double вносит два модуля глубине, и значение любого другого типа вносит один модуль.

3.6.3 Динамическое подключение

Каждый фрейм (§3.6) содержит ссылку на пул константы этапа выполнения (§3.5.5) для типа текущего метода, чтобы поддерживать динамическое подключение кода метода. class код файла для метода обращается к методам, которые будут вызваны и переменные, которые будут получены доступ через символьные ссылки. Динамическое подключение преобразовывает эти символьные ссылки метода в конкретные ссылки метода, загружая классы по мере необходимости, чтобы разрешить пока еще неопределенные символы, и преобразовывает переменные доступы в соответствующие смещения в структурах хранения, связанных с расположением времени выполнения этих переменных.

Это позднее связывание методов и переменных производит изменения в других классах, которые метод использует менее вероятно, чтобы повредить этот код.

3.6.4 Нормальное Завершение Вызова метода

Вызов метода обычно завершается, если тот вызов не заставляет исключение (§2.16, §3.10) быть брошенным, или непосредственно от виртуальной машины Java или в результате выполнения явного throw оператор. Если вызов текущего метода обычно завершается, то значение может быть возвращено к методу вызова. Это происходит, когда вызванный метод выполняет одну из инструкций возврата (§3.11.8), выбор которого должен быть подходящим для типа возвращаемого значения (если любой).

Текущий фрейм (§3.6) используется в этом случае, чтобы восстановить состояние invoker, включая его локальные переменные и стек операнда, со счетчиком программы invoker, соответственно постепенно увеличенного, чтобы пропустить мимо инструкции вызова метода. Выполнение тогда обычно продолжается во фрейме метода вызова с возвращенным значением (если любой), продвигал на стек операнда того фрейма.

3.6.5 Резкое Завершение Вызова метода

Вызов метода завершается резко, если выполнение инструкции виртуальной машины Java в пределах метода заставляет виртуальную машину Java выдавать исключение (§2.16, §3.10), и то исключение не обрабатывается в пределах метода. Выполнение athrow инструкции также заставляет исключение быть явно брошенным и, если исключение не поймано текущим методом, результатами в резком завершении вызова метода. Вызов метода, который не завершает резко никогда возвраты значение к его invoker.

3.6.6 Дополнительная информация

Фрейм может быть расширен с помощью дополнительной специфичной для реализации информации, такой как отладочная информация.


3.7 Представление Объектов

Виртуальная машина Java не передает под мандат определенной внутренней структуры для объектов 8


3.8 Арифметика с плавающей точкой

Виртуальная машина Java включает подмножество арифметики с плавающей точкой, определенной в Стандарте IEEE для Двоичной Арифметики С плавающей точкой (Станд. ANSI/IEEE 754-1985, Нью-Йорк).

3.8.1 Виртуальная машина Java Арифметика С плавающей точкой и IEEE 754

Основные отличия между арифметикой с плавающей точкой, поддерживаемой виртуальной машиной Java и стандартом IEEE 754:

3.8.2 Режимы с плавающей точкой

У каждого метода есть режим с плавающей точкой, который или строг FP или не строг FP. Режим с плавающей точкой метода определяется установкой ACC_STRICT бит access_flags элемент method_info структура (§4.6) определение метода. Метод, для которого устанавливается этот бит, строг FP; иначе, метод не строг FP.

Отметьте что это отображение ACC_STRICT бит подразумевает, что методы в классах, скомпилированных компилятором, который предшествует Java 2 платформы, v1.2, эффективно не строги FP.

Мы будем именовать стек операнда как наличие данного режима с плавающей точкой, когда метод, у вызова которого, создаваемого фрейм, содержащий стек операнда, есть тот режим с плавающей точкой. Точно так же мы будем именовать инструкцию виртуальной машины Java как наличие данного режима с плавающей точкой, когда у метода, содержащего ту инструкцию, будет тот режим с плавающей точкой.

Если набор значений "расширенная экспонента плавающая" поддерживается (§3.3.2), значения типа float на стеке операнда, который не строг FP, может передвинуться на тот набор значений кроме где запрещено преобразованием набора значений (§3.8.3). Если набор значений "двойная расширенная экспонента" поддерживается (§3.3.2), значения типа double на стеке операнда, который не строг FP, может передвинуться на тот набор значений кроме где запрещено преобразованием набора значений.

Во всех других контекстах, ли на стеке операнда или в другом месте, и независимо от режима с плавающей точкой, значений с плавающей точкой типа float и double май только передвигается на набор значений плавающий и двойной набор значений, соответственно. В частности класс и поля экземпляра, элементы массива, локальные переменные, и параметры метода могут только содержать значения, оттянутые из стандартных наборов значений.

3.8.3 Преобразование Набора значений

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

Где преобразование набора значений обозначается, реализации разрешают выполнить одну из следующих операций на значении:

Такие необходимые преобразования набора значений могут произойти в результате передачи параметра типа с плавающей точкой во время вызова метода, включая native вызов метода; возврат значения типа с плавающей точкой от метода, который не строг FP к методу, который строг FP; или хранение значения типа с плавающей точкой в локальную переменную, поле, или массив в методе, который не строг FP.

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

Преобразование набора значений сохраняет бесконечности и NaNs и не может изменить знак преобразовываемого значения. Преобразование набора значений не имеет никакого эффекта на значение, которое не имеет типа с плавающей точкой.


3.9 Особенно Названные Методы Инициализации

На уровне виртуальной машины Java каждый конструктор (§2.12) появляется как метод инициализации экземпляра, который имеет специальное имя <init>. Это имя предоставляется компилятором. Поскольку имя <init> не допустимый идентификатор, он не может использоваться непосредственно в программе, записанной в языке программирования Java. Методы инициализации экземпляра могут быть вызваны только в пределах виртуальной машины Java invokespecial инструкцией, и они могут быть вызваны только на неинициализированных экземплярах класса. Метод инициализации экземпляра берет права доступа (§2.7.4) конструктора, из которого он был получен.

Класс или интерфейс имеют самое большее один класс или интерфейсный метод инициализации и инициализируются (§2.17.4), вызывая тот метод. Метод инициализации класса или интерфейса статичен и не берет параметров. У этого есть специальное имя <clinit>. Это имя предоставляется компилятором. Поскольку имя <clinit> не допустимый идентификатор, он не может использоваться непосредственно в программе, записанной в языке программирования Java. Класс и интерфейсные методы инициализации вызываются неявно виртуальной машиной Java; они никогда не вызываются непосредственно ни от какой инструкции виртуальной машины Java, но вызываются только косвенно как часть процесса инициализации класса.


3.10 Исключения

В языке программирования Java, бросая исключение результаты в непосредственную нелокальную передачу управления от точки, где исключение было выдано. Эта передача управления может резко завершить, один за другим, многократные операторы, вызовы конструктора, статичные и полевые оценки инициализатора, и вызовы метода. Процесс продолжается до a catch пункт (§2.16.2) находится, который обрабатывает брошенное значение. Если никакой такой пункт не может быть найден, выходы текущего потока.

В случаях, где a finally пункт (§2.16.2) используется, finally пункт выполняется во время распространения исключения, выданного от связанного try блок и любой связались catch блок, даже если нет catch пункт, который обрабатывает выданное исключение, может быть найден.

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

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

Порядок, в котором обработчики исключений метода ищутся соответствие, важен. В пределах a class файл обработчики исключений для каждого метода хранится в таблице (§4.7.3). Во время выполнения, когда исключение выдается, виртуальная машина Java ищет обработчики исключений текущего метода в порядке, что они появляются в соответствующей таблице обработчиков исключений в class файл, запускающийся с начала той таблицы. Поскольку try операторы структурируются, компилятор для языка программирования Java может всегда упорядочивать записи таблицы обработчиков исключений так, что, для любого выданного исключения и любого значения счетчика программы в том методе, первый обработчик исключений, который соответствует выданное исключение, соответствует самому внутреннему соответствию catch или finally пункт.

Отметьте, что виртуальная машина Java не осуществляет вложение или любое упорядочивание записей таблицы исключений метода (§4.9.5). Семантика обработки исключений языка программирования Java реализуется только через сотрудничество с компилятором. Когда class файлы сгенерированы некоторыми другими средствами, определенная поисковая процедура гарантирует, что все виртуальные машины Java будут последовательно вести себя.

Больше информации о реализации catch и finally пункты даются в Главе 7, "Компилируя для виртуальной машины Java."


3.11 Сводки Набора команд

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

Игнорируя исключения, внутренний цикл интерпретатора виртуальной машины Java эффективно

do {
     fetch an opcode;
     if (operands) fetch operands;
     execute the action for the opcode;
} while (there is more to do);
Число и размер операндов определяются кодом операции. Если операнд составляет больше чем один байт в размере, то это сохранено в байте старшего разряда порядка с обратным порядком байтов сначала. Например, 16-разрядный индекс без знака в локальные переменные сохранен как два байта без знака, byte1 и byte2, так, что его значение

(byte1 << 8) | byte2
Поток команд байт-кода только однобайтовый выровненный. Эти два исключения являются tableswitch и lookupswitch инструкциями, которые дополняются, чтобы вызвать внутреннее выравнивание некоторых из их операндов на 4-байтовых границах.

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

3.11.1 Типы и виртуальная машина Java

Большинство инструкций в наборе команд виртуальной машины Java кодирует информацию о типе об операциях, которые они выполняют. Например, iload инструкция загружает содержание локальной переменной, которая должна быть int, на стек операнда. fload инструкция делает то же самое с a float значение. Эти две инструкции могут иметь идентичные реализации, но иметь отличные коды операций.

Для большинства введенных инструкций тип инструкции представляется явно в мнемосхеме кода операции буквой: я для int работа, l для long, s для short, b для byte, c для char, f для float, d для double, и для reference. У некоторых инструкций, для которых тип однозначен, нет буквы типа в их мнемосхеме. Например, arraylength всегда работает на объекте, который является массивом. Некоторые инструкции, такие как goto, безусловная передача управления, не работают на введенных операндах.

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

Таблица 3.2 суммирует поддержку типа в наборе команд виртуальной машины Java. Конкретная инструкция, с информацией о типе, создается, заменяя T в шаблоне инструкции в столбце кода операции буквой в столбце типа. Если столбец типа для некоторого шаблона инструкции и типа является пробелом, то никакая инструкция не существует, поддерживая тот тип работы. Например, есть инструкция загрузки для типа int, iload, но нет никакой инструкции загрузки для типа byte.

Отметьте, что у большинства инструкций в Таблице 3.2 нет форм для целочисленных типов byte, char, и short. Ни у одного нет форм для boolean ввести. Компиляторы кодируют загрузки литеральных значений типов byte и short использование инструкций виртуальной машины Java, которые подписываются - расширяет те значения до значений типа int во время компиляции или время выполнения. Загрузки литеральных значений типов boolean и char кодируются, используя инструкции, которые обнуляют - расширяют литерал до значения типа int во время компиляции или время выполнения. Аналогично, загрузки из массивов значений типа boolean, byte, short, и char кодируются, используя инструкции виртуальной машины Java, которые подписываются - расширяют или обнуляют - расширяют значения до значений типа int. Таким образом, большинство операций на значениях фактических типов boolean, byte, char, и short правильно выполняются инструкциями, работающими на значениях вычислительного типа int.

код операции байт короткий интервал долго плавание двойной случайная работа ссылка
Tipush bipush sipush
Tconst iconst lconst fconst dconst aconst
Tload iload lload fload dload aload
Tstore istore lstore fstore dstore astore
Tinc iinc
Taload baload saload iaload laload faload daload caload aaload
Tastore bastore sastore iastore lastore fastore dastore castore aastore
Tadd iadd ladd fadd dadd
Tsub isub lsub fsub dsub
Tmul imul lmul fmul dmul
Tdiv idiv ldiv fdiv ddiv
Trem irem lrem frem drem
Tneg ineg lneg fneg dneg
Tshl ishl lshl
Tshr ishr lshr
Tushr iushr lushr
Tand iand земля
Скалистая вершина ior lor
Txor ixor lxor
i2T i2b i2s i2l i2f i2d
l2T l2i l2f l2d
f2T f2i f2l f2d
d2T d2i d2l d2f
Tcmp lcmp
Tcmpl fcmpl dcmpl
Tcmpg fcmpg dcmpg
if_TcmpOP if_icmpOP if_acmpOP
Treturn ireturn lreturn freturn dreturn areturn


Отображение между виртуальной машиной Java фактические типы и виртуальной машиной Java вычислительные типы получается в итоге Таблицей 3.3.

Фактический Тип Вычислительный Тип Категория
boolean int категория 1
byte int категория 1
char int категория 1
short int категория 1
int int категория 1
float float категория 1
reference reference категория 1
returnAddress returnAddress категория 1
long long категория 2
double double категория 2


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

Остаток от этой главы суммирует набор команд виртуальной машины Java.

3.11.2 Загрузка и Инструкции Хранилища

Загрузка и инструкции хранилища передают значения между локальными переменными (§3.6.1) и стек операнда (§3.6.2) фрейма виртуальной машины Java (§3.6):

Инструкции, что поля доступа объектов и элементы массивов (§3.11.5) также передают данные и от стека операнда.

Мнемоники команд, показанные выше с запаздывающими буквами между угловыми скобками (например, iload _ <n>), обозначают семейства инструкций (с элементами iload_0, iload_1, iload_2, и iload_3 в случае iload _ <n>). Такие семейства инструкций являются специализациями дополнительной универсальной инструкции (iload), который берет один операнд. Для специализированных инструкций операнд неявен и не должен быть сохранен или выбран. Семантика является иначе тем же самым (iload_0, означает ту же самую вещь как iload с операндом 0). Буква между угловыми скобками определяет тип неявного операнда для того семейства инструкций: для <n>, неотрицательного целого числа; для <i>, int; для <l>, a long; для <f>, a float; и для <d>, a double. Формы для типа int используются во многих случаях, чтобы выполнить операции на значениях типа byte, char, и short (§3.11.1).

Эта нотация для семейств инструкции используется всюду по Спецификации Виртуальной машины JavaTM.

3.11.3 Арифметические Инструкции

Арифметические инструкции вычисляют результат, который обычно является функцией двух значений на стеке операнда, продвигая результат назад на стеке операнда. Есть два основных вида арифметических инструкций: те, которые работают на целочисленных значениях и тех, которые работают на значениях с плавающей точкой. В пределах каждого из этих видов арифметические инструкции специализируются к виртуальной машине Java числовые типы. Нет никакой прямой поддержки целочисленной арифметики на значениях byte, short, и char типы (§3.11.1), или для значений boolean введите; те операции обрабатываются инструкциями, работающими на типе int. Целочисленные и инструкции с плавающей точкой также отличаются по их поведению на переполнении и делятся на нуль. Арифметические инструкции следующие:

Семантика операторов языка программирования Java на целом числе и значениях с плавающей точкой (§2.4.2, §2.4.4) непосредственно поддерживается семантикой набора команд виртуальной машины Java.

Виртуальная машина Java не указывает на переполнение во время операций на целочисленных типах данных. Единственные целочисленные операции, которые могут выдать исключение, являются целочисленными инструкциями дележа (idiv и ldiv) и целочисленными инструкциями остатка (irem и lrem), которые бросают ArithmeticException если делитель является нулем.

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

Виртуальная машина Java требует, чтобы арифметика с плавающей точкой вела себя как будто каждый оператор с плавающей точкой, округленный ее результат с плавающей точкой к точности результата. Неточные результаты должны быть округлены к представимому значению, самому близкому к бесконечно точному результату; если два самых близких представимых значения одинаково рядом, тот, имеющий младший значащий бит нуля, выбирается. Это - значение по умолчанию стандарта IEEE 754 округление режима, известного как вокруг самому близкому режиму.

Виртуальная машина Java использует IEEE 754 вокруг к нулевому режиму, преобразовывая значение с плавающей точкой в целое число. Это приводит к числу, являющемуся усеченным; отбрасываются любые биты мантиссы, которые представляют дробную часть значения операнда. Вокруг к нулевому режиму выбирает как его результат значение типа, самое близкое к, но не больше в величине чем, бесконечно точный результат.

Операторы виртуальной машины Java с плавающей точкой не бросают исключения на этапе выполнения (чтобы не быть перепутанными с IEEE 754 исключения с плавающей точкой). Работа, которая переполнения производят бесконечность со знаком, работа, которая потери значимости производят денормализованное значение или нуль со знаком, и работа, у которой нет никакого математически определенного результата, производит НЭН. Все числовые операции с НЭН как операнд производят НЭН в результате.

Сравнения на значениях типа long (lcmp) выполняют сравнение со знаком. Сравнения на значениях типов с плавающей точкой (dcmpg, dcmpl, fcmpg, fcmpl) выполняются, используя IEEE 754 несигнальные сравнения.

3.11.4 Инструкции Преобразования типов

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

Виртуальная машина Java непосредственно поддерживает следующие расширяющиеся числовые преобразования:

Расширяющиеся числовые инструкции преобразования являются i2l, i2f, i2d, l2f, l2d, и f2d. Мнемоника для этих кодов операций прямая данный соглашения о присвоении имен для введенных инструкций и каламбурящего использования 2, чтобы значить "для". Например, i2d инструкция преобразовывает int оцените a double. Расширяющиеся числовые преобразования не теряют информацию о полной величине числового значения. Действительно, преобразования, расширяющиеся от int к long и int к double не теряйте информацию вообще; числовое значение сохраняется точно. Преобразования, расширяющиеся от float к double это строго FP (§3.8.2), также сохраняют числовое значение точно; однако, такие преобразования, которые не строги FP, могут потерять информацию о полной величине преобразованного значения.

Преобразование int или a long значение к float, или a long значение к double, может потерять точность, то есть, может потерять некоторые из младших значащих битов значения; получающееся значение с плавающей точкой является правильно округленной версией целочисленного значения, используя IEEE 754 вокруг для самого близкого режима.

Расширяющееся числовое преобразование int к a long просто знак - расширяет two's-дополнительное представление int значение, чтобы заполнить более широкий формат. Расширяющееся числовое преобразование a char к нулю целочисленного типа - расширяет представление char значение, чтобы заполнить более широкий формат.

Несмотря на то, что потеря точности может произойти, расширяя числовые преобразования никогда не заставляет виртуальную машину Java бросать исключение на этапе выполнения (чтобы не быть перепутанной с IEEE 754 исключение с плавающей точкой).

Отметьте, что расширяющиеся числовые преобразования не существуют от целочисленных типов byte, char, и short вводить int. Как отмечено в §3.11.1, значениях типа byte, char, и short внутренне расширяются до типа int, создание этих неявных преобразований.

Виртуальная машина Java также непосредственно поддерживает следующие сужающиеся числовые преобразования:

Сужающиеся числовые инструкции преобразования являются i2b, i2c, i2s, l2i, f2i, f2l, d2i, d2l, и d2f. Сужающееся числовое преобразование может привести к значению различного знака, различного порядка величины, или обоих; это может, таким образом, потерять точность.

Сужающееся числовое преобразование int или long к целочисленному типу T просто отбрасывает все кроме битов самых низкоуровневых N, где N является числом битов, используемых, чтобы представить тип T. Это может заставить получающееся значение не иметь тот же самый знак как входное значение.

В сужающемся числовом преобразовании значения с плавающей точкой к целочисленному типу T, где T также int или long, значение с плавающей точкой преобразовывается следующим образом:

Сужающееся числовое преобразование из double к float ведет себя в соответствии с IEEE 754. Результат правильно округляется, используя IEEE 754 вокруг для самого близкого режима. Значение, слишком маленькое, чтобы быть представленным как a float преобразовывается в положительный или отрицательный нуль типа float; значение, слишком большое, чтобы быть представленным как a float преобразовывается в положительную или отрицательную бесконечность. A double НЭН всегда преобразовывается в a float НЭН.

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

3.11.5 Объектное Создание и Манипулирование

Хотя и экземпляры класса и массивы являются объектами, виртуальная машина Java создает и управляет экземплярами класса и массивами, использующими отличные наборы инструкций:

3.11.6 Инструкции управления Стеком операнда

Много инструкций обеспечиваются для непосредственного управления стеком операнда: появитесь, pop2, дубликат, dup2, dup_x1, dup2_x1, dup_x2, dup2_x2, подкачка.

3.11.7 Инструкции Передачи управления

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

У виртуальной машины Java есть отличные наборы инструкций, которые условно переходят на сравнении с данными int и reference типы. У этого также есть отличные команды условного перехода, которые тестируют на нулевую ссылку, и таким образом не обязан определять конкретное значение для null (§3.4).

Условные переходы на сравнениях между данными типов boolean, byte, char, и short выполняются, используя int инструкции сравнения (§3.11.1). Условный переход на сравнении между данными типов long, float, или double инициируется, используя инструкцию, которая сравнивает данные и производит int результат сравнения (§3.11.3). Последующее int инструкция сравнения тестирует этот результат и производит условный переход. Из-за его акцента на int сравнения, виртуальная машина Java обеспечивает богатое дополнение команд условного перехода для типа int.

Все int условные инструкции передачи управления выполняют подписанные сравнения.

3.11.8 Вызов метода и Инструкции Возврата

Следующий четырем инструкциям вызывает методы:

Инструкции возврата метода, которые отличает тип возврата, являются ireturn (привыкший к возвращаемым значениям типа boolean, byte, char, short, или int), lreturn, freturn, dreturn, и areturn. Кроме того, инструкция возврата используется, чтобы возвратиться из методов, которые, как объявляют, были void, методы инициализации экземпляра, и класс или интерфейсные методы инициализации.

3.11.9 Выдача Исключений

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

3.11.10 Реализация finally

Реализация finally ключевое слово использует jsr, jsr_w, и мочите инструкции. См. Раздел 4.9.6, "Исключения и наконец," и Раздел 7.13, "Компилируя наконец."

3.11.11 Синхронизация

Виртуальная машина Java поддерживает синхронизацию и методов и последовательностей инструкций в пределах метода, используя единственную конструкцию синхронизации: монитор.

Синхронизация на уровне метода обрабатывается как часть вызова метода и возврата (см. Раздел 3.11.8, "Вызов метода и Инструкции Возврата").

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

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

Компилятор осуществляет надлежащее соединение monitorenter и monitorexit инструкций по резкому завершению вызова метода, генерируя обработчики исключений (§3.10), который будет соответствовать любое исключение и чей связанный код выполняет необходимые monitorexit инструкции (§7.14).


3.12 Библиотеки классов

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

Классы, которые могли бы потребовать специальной поддержки от виртуальной машины Java, включают тех, которые поддерживают:

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


3.13 Общедоступных Проекта, Частная Реализация

К настоящему времени эта книга делала набросок общедоступного представления виртуальной машины Java: class формат файла и набор команд. Эти компоненты жизненно важны для аппаратных средств - операционная система - и независимость реализации виртуальной машины Java. Конструктор может предпочесть думать о них как о средстве надежно передать фрагменты программ между узлами каждая реализация Java или Java 2 платформы, а не как проект, который будет сопровождаться точно.

Важно понять, где строка между общедоступным проектом и частной реализацией находится. Реализация виртуальной машины Java должна быть в состоянии читать class файлы и должны точно реализовать семантику кода виртуальной машины Java там. Один способ сделать это состоит в том, чтобы взять этот документ в качестве спецификации и реализовывать ту спецификацию буквально. Но это является также совершенно выполнимым и требуемым для конструктора, чтобы изменить или оптимизировать реализацию в пределах ограничений этой спецификации. Пока class формат файла может быть считан, и семантика его кода сохраняются, конструктор может реализовать их семантика всегда. То, что "под капотом", является бизнесом конструктора, пока корректный внешний интерфейс тщательно сохраняется 10

Конструктор может использовать эту гибкость, чтобы адаптировать реализации виртуальной машины Java для высокой производительности, низкое использование памяти, или мобильность. То, что имеет смысл в данной реализации, зависит от целей той реализации. Диапазон опций реализации включает следующее:

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


1 первый выпуск Спецификации Виртуальной машины JavaTM не рассматривал boolean быть типом виртуальной машины Java. Однако, boolean у значений действительно есть ограниченная поддержка в виртуальной машине Java. Этот второй выпуск разъясняет проблему, обрабатывая boolean как тип.

2 В выпусках 1.0 и 1.1 JDK Sun, и Java 2 SDK, Standard Edition, v1.2, boolean массивы в языке программирования Java кодируются как виртуальная машина Java byte массивы, используя 8 битов на boolean элемент.

3 В первом выпуске этой спецификации, стек виртуальной машины Java был известен как стек Java.

4 В реализациях Sun виртуальной машины Java в выпусках 1.0.2 и 1.1 JDK, и Java 2 SDK, Standard Edition, v1.2, стеки виртуальной машины Java являются несмежными и независимо расширяются как требуется вычислением. Те реализации не освобождают память, выделенную для стека виртуальной машины Java, пока связанный поток не завершается. Расширение подвергается пределу размера для любого стека. Предел размера стека виртуальной машины Java может быть установлен для запуска виртуальной машины, используя"-oss"флаг. Предел размера стека виртуальной машины Java может использоваться, чтобы ограничить потребление памяти или поймать безудержные рекурсии.

Реализации 5 Sun виртуальной машины Java в выпусках 1.0.2 и 1.1 JDK, и Java, 2 SDK, Standard Edition, v1.2, динамически разворачивают "кучу" как требуется вычислением, но никогда не сокращают "кучу". Начальные и максимальные размеры могут быть определены на запуске виртуальной машины, используя"-ms"и"-mx"флаги, соответственно.

Реализация 6 Sun виртуальной машины Java в выпуске 1.0.2 JDK динамически разворачивает область метода как требуется вычислением, но никогда не сокращает область метода. Реализации виртуальной машины Java в выпуске 1.1 JDK Sun и Java 2 SDK, Standard Edition, v1.2 собирают "мусор" область метода. Ни в том, ни в другом случае контроль за работой пользователей по начальной букве, минимуму, или максимальному размеру обеспеченной области метода.

Реализации 7 Sun виртуальной машины Java в выпусках 1.0.2 и 1.1 JDK, и Java 2 SDK, Standard Edition, v1.2, выделяют фиксированный размер собственные стеки метода единственного размера. Размер собственных стеков метода может быть установлен на запуске виртуальной машины, используя"-ss"флаг. Собственный предел размера стека метода может использоваться, чтобы ограничить потребление памяти или поймать безудержные рекурсии в native методы. Реализации Sun не проверяют на собственное переполнение стека метода.

8 В некоторых из реализаций Sun виртуальной машины Java, ссылка на экземпляр класса является указателем на дескриптор, который является самостоятельно парой указателей: один к таблице, содержащей методы объекта и указателя на Class объект, который представляет тип объекта, и другой к памяти, выделенной от "кучи" для объектных данных.

9 Слабых ссылок были представлены в Java 2 платформы, v1.2.

10 есть некоторые исключения: отладчики, профилировщики, и своевременные генераторы кода могут каждый потребовать доступа к элементам виртуальной машины Java, которые, как обычно полагают, являются "под капотом." Где необходимо Sun работает с другими конструкторами виртуальной машины Java и поставщиками инструментов, чтобы разработать общие интерфейсы к виртуальной машине Java для использования такими инструментами, и продвинуть те интерфейсы через отрасль. Информация о публично доступных низкоуровневых интерфейсах к виртуальной машине Java будет сделана доступной в http://java.sun.com.

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

Спецификация Виртуальной машины JavaTM
Авторское право © Sun Microsystems, Inc 1999 года. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления к jvm@java.sun.com

free hit counter