1 Архитектура виртуальной машины языка Ява

1.1 - Поддерживаемые типы данных
1.2 - Регистры
1.3 - Локальные переменные
1.4 - Стек операндов
1.5 - Среда выполнения
1.6 - Куча и сборщик мусора
1.7 - Область метода
1.8 - Набор инструкций Ява
1.9 - Ограничения


1.1 Поддерживаемые типы данных

Типы данных виртуальной машины содержат основные типы данных языка Ява:

byte   // 1-байтовое со знаком,представленное в дополнительном обратном коде
short  // 2-байтовое со знаком,представленное в дополнительном обратном коде
int    // 4-байтовое со знаком,представленное в дополнительном обратном коде
long   // 8-байтовое со знаком,представленное в дополнительном обратном коде
float  // вещественное число одинарной точности стандарта IEEE 754, занимающее 4 байта
double // вещественное число двойной точности стандарта IEEE 754, занимающее 8 байт
char   // символ Unicode, занимающий 2 байта

В Яве проверка почти всех типов производится во время компиляции. Данные элементарных типов, указанных выше, не требуют  аппаратной поддержки тегов чтобы обеспечит исполнение Ява-кода. Вместо этого, существуют байткоды, которые работают с элементарными значениями и указывают типы операндов, например, каждая из инструкций iadd, ladd, fadd, и dadd складывает два числа имеющих типы int, long, float, и double, соответственно.

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

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

Другие типы данных виртуальной машины включают:

object // ссылка на объект Явы, занимающая 4 байта
returnAddress // 4 байта, используемые с инструкциями jsr/ret/jsr_w/ret_w

Заметьте: в Яве массивы трактуются как объекты.

Эта спецификация не определяет никакой внутренней структуры для объектов. В нашей реализации объектная ссылка - это дескриптор, который является парой указателей: один на таблицу методов для объекта, и другой на данные, соответствующие объекту. Другие реализации могут использовать встроенное кэширование вместо таблицы методов; такие методы, вероятно, будут работать быстрее на аппаратных средствах ЭВМ, которые будут появляться до 2000 года.

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

Может показаться, что Виртуальная Машина языка Ява предусматривает исполнение байткода только на компьютерах 32-битной адресацией. Однако возможно построение версии Виртуальной Машины языка Ява, которая автоматически переводит байткоды в 64-битную форму. Описание такого преобразования не содержится в этой спецификации.


1.2 Регистры

Виртуальная машина в любой момент времени выполняет код отдельного метода, и регистр PC содержит адрес следующего байткода, который будет выполнятся.

Для каждого метода выделяется место в памяти для хранения:

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

Все эти регистры 32 битные.


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

Каждый Ява-метод использует набор локальных переменных фиксированного размера. Они адресуются, как смещения слова от регистра vars. Ширина локальных переменных 32 бита.

Длинные целые и вещественные двойной точности рассматриваются, как располагающиеся в двух локальных переменных, и адресуются индексом первой локальной переменной. (Например, локальная переменная с индексом n содержащая вещественное двойной точности фактически занимает место, соответствующее индексам n и n + 1.) Спецификация виртуальной машины не требует выравнивания 64-битных значений локальных переменных на 64 битную границу. Разработчикам предоставляется право самим разделять длинные целые и вещественные двойной точности на два слова.

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


1.4 Стек операндов

Все инструкции машины берут операнды от стека операндов, работают с ними, и возвращают результат обратно в стек. Мы выбрали стековую организацию так, чтобы было легко эффективно эмулировать машину на машинах с немногими регистрами или при нерегулярном наборе регистров типа Intel 486.

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

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

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

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

Ниже в нашем описании инструкций виртуальной машины результат выполнения инструкции на стеке операндов представлен текстуально, каждое 32-битное слово на стеке записывается отдельно, в порядке слева направо. Таким образом:

Стек: ..., value1, value2 = > ..., value3

показывает действие, которое начинается при наличии value2 на вершине стека и

value1 под ним. В результате выполнения инструкции, value1 и value2 извлекаются из стека и заменяются на value3, которое было вычислено инструкцией. Остаток стека, представленный многоточием, не затрагивается при выполнении инструкции.

Типы long и double занимают два 32-битных слова на стеке операндов:

Стек: ... = > ..., value-word1, value-word2

Эта спецификация не описывает, как два слова выделяются из 64-битного long или double; надо только учитывать, чтобы конкретная реализация была внутренне непротиворечивой.


1.5 Среда выполнения

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

Динамическая компоновка

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

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

Нормальные возвраты из методов

Если выполнение текущего метода заканчивается, то значение возвращается в вызывающий метод. Это происходит когда вызываемый метод выполняет инструкцию возврата, соответствующую  возвращаемому типу.

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

Исключение и распространение ошибки

Исключительные состояния, известные в Яве как Error или Exception, являются подклассами Throwable и могут возникать в программе из-за:

Когда генерируется исключение:

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

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


1.6 Куча и сборка мусора

Куча в Яве является областью данных времени выполнения, в которой размещаются экземпляры классов (объекты). В языке Ява предусмотрен сборщик мусора - это  дает программисту возможность не освобождать память для объектов явно. Ява не предполагает никакого конкретного варианта сборщика мусора; могут использоваться различные алгоритмы в зависимости от требований системы.


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

Область метода аналогична месту в памяти, которое отводится для компилируемого кода в обычных языках или текстовому сегменту в процессе UNIX. Она хранит код метода (скомпилированный Ява-код) и таблицы символов. В текущей реализации Явы код метода - это не часть кучи, обслуживаемой сборщиком мусора, хотя это планируется сделать в следующем выпуске.


1.8 Набор инструкций языка Ява

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

Внутренний цикл исполнения виртуальной машины эффективен:

do {
    выбор байт кода операции
    выполнение действия в зависимости от значения кода
} while (еще нужно выполнять);

Число и размер дополнительных операндов определяется кодом операции. Если дополнительный операнд содержит более одного байта, то они хранятся в порядке от старшего к младщему - первым является старший байт. Например, 16-битный параметр хранится как два байта, значение которого:

first_byte * 256 + second_byte

Поток команд байткода выравнивается только по границе байта, за исключением инструкций tableswitch и lookupswitch, которые выравниваются по 4-байтовой границе в пределах этих инструкций.

Эти соглашения сохраняют код виртуальной машины для скомпилированных  Ява-программ компактным и отражают преимущественное стремление к компактности.


1.9 Ограничения

На один класс в константном пуле отводится максимум 65535 элементов. Это ограничение является внутренним пределом для общей сложности одного класса.

Длина кода метода ограничена 65535 байтами, определяемыми размерами индексов в коде, в таблице исключений, таблице номеров строк и таблице локальных переменных. Это может быть зафиксировано для 1.0beta2.

Кроме этого предела, существует только одно ограничение - число слов аргументов в вызове метода ограничено 255.