2. Фреймы

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

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

Размер массива локальных переменных и стека операндов определяется на этапе компиляции программы.

2.1. Регистры JVM

Рис.4. Фрейм и регистры JVM.

Для управления исполнением байткода JVM использует 4 32-битных регистра:

  1. pc (program counter) - счётчик команд.
  2. vars - указывает на массив локальных переменных текущего метода.
  3. frame - указывает на текущую среду выполнения. Среда выполнения представляет собой структуру, которая может различаться в зависимости от реализации виртуальной машины. Эта структура содержит информацию, необходимую для динамической компоновки методов, обработки исключений и др.
  4. optop - указывает на вершину стека операндов.

2.2. Типы данных JVM

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

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

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

Существуют ещё 2 типа данных, с которыми работает виртуальная машина Java: ссылка на объект (reference) и адрес возврата(returnAddress). Значения типа returnAddress представляют собой указатели на инструкции байткода JVM. В отличие от численных типов, тип returnAddress не соответствует ни одному типу языка программирования Java и не может быть изменён выполняемой программой.

Таблица 1. Типы данных виртуальной машины Java.

Тип Описание
byte 1-байтовое двоичное целое со знаком в дополнительном коде.
short 2-байтовое двоичное целое со знаком в дополнительном коде.
int 4-байтовое двоичное целое со знаком в дополнительном коде.
long 8-байтовое двоичное целое со знаком в дополнительном коде.
char Символ Unicode, занимающий 2 байта.
float Вещественное число одинарной точности стандарта IEEE 754. Размер 4 байта.
double Вещественное число двойной точности стандарта IEEE 754. Размер 8 байтов.
reference Ссылка на объект Java. Размер 4 байта.
returnAddress Адрес возврата. Размер 4 байта.

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

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

Рис.5. Локальные переменные.

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

2.4. Стек операндов

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

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

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

Рис.6. Сложение двух величин типа int.

Рис.7. Сложение двух величин типа double.

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

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

Наверх | Дальше
Королёв А.В. ИС-310 2006г.