Spec-Zone .ru
спецификации, руководства, описания, API
|
Содержание | Предыдущий | Следующий | Индекс | Спецификация Виртуальной машины JavaTM |
ГЛАВА 3
Эта книга определяет абстрактную машину. Это не документирует определенной реализации виртуальной машины Java, включая Sun.
Чтобы реализовать виртуальную машину Java правильно, Вы должны только быть в состоянии считать Java class
формат файла и правильно выполняет операции, определенные там. Детали реализации, которые не являются частью спецификации виртуальной машины Java, излишне ограничили бы творческий потенциал конструкторов, и будут только обеспечены, чтобы сделать выставку более четкой. Например, расположение памяти областей данных времени выполнения, алгоритм сборки "мусора", используемый, и любая оптимизация байт-кодов (например, преобразовывая их в машинный код), оставляют усмотрению конструктора.
Виртуальная машина Java ожидает, что почти вся проверка типа делается во время компиляции, не виртуальной машиной Java непосредственно. В частности данные не должны быть тегированы или иначе быть inspectable, чтобы определить типы. Вместо этого набор команд виртуальной машины Java отличает свои инструкции использования типов операнда, предназначенные, чтобы работать на значениях определенных типов. Например, iadd
, ladd
, fadd
, и dadd
все инструкции виртуальной машины Java, которые добавляют два числовых значения, но они требуют операндов, типы которых int
, long
, float
, и double
, соответственно. Для сводки поддержки типа в наборе команд виртуальной машины Java см. §3.11.1.
Виртуальная машина Java содержит явную поддержку объектов. Объект является или динамически выделенным экземпляром класса или массивом. У ссылки на объект, как полагают, есть тип виртуальной машины Java reference
. Значения типа reference
может считаться указателями на объекты. Больше чем одна ссылка может существовать к объекту. Хотя виртуальная машина Java выполняет операции на объектах, она никогда не адресует их непосредственно. На объектах всегда управляют, передаются, и тестируются через значения типа reference
.
returnAddress
ввести. Числовые типы состоят из целочисленных типов: byte
, чьи значения являются 8-разрядными two's-дополнительными целыми числами со знаком
short
, чьи значения являются 16-разрядными two's-дополнительными целыми числами со знаком
int
, чьи значения являются 32-разрядными two's-дополнительными целыми числами со знаком
long
, чьи значения являются 64-разрядными two's-дополнительными целыми числами со знаком
char
, чьи значения являются 16-разрядными целыми без знака, представляющими символы версии 1.1.5 Unicode (§2.1)
float
, чьи значения являются 32-разрядным IEEE 754 числа с плавающей точкой
double
, чьи значения являются 64-разрядным IEEE 754 числа с плавающей точкой returnAddress
тип является указателями на коды операций инструкций виртуальной машины Java. Только returnAddress
тип не является типом языка Java.byte
, от -128
к 127
(-27 к 27-1), включительно
short
, от -32768
к 32767
(-215 к 215-1), включительно
int
, от -2147483648
к 2147483647
(-231 к 231-1), включительно
long
, от -9223372036854775808
к 9223372036854775807
(-263 к 263-1), включительно
char
, от 'u0000'
к 'uffff'
; char
без знака, таким образом, 'uffff'
представляет 65535
когда использующийся в выражениях, не -1
float
и double
представьте 32-разрядную одинарную точность и значения формата IEEE 754 64-битов двойной точности как определено в Стандарте IEEE для Двоичной Арифметики С плавающей точкой, Станд. ANSI/IEEE 754-1985 (IEEE, Нью-Йорк). Стандарт IEEE 754 включает не только положительный и числа величины знака минус, но также и положительный, и отрицательный обнуляет, положительные и отрицательные бесконечности, и специальное Не-число (после этого сокращал НЭН), значение, которое используется, чтобы представить результат определенных операций, таких как делящийся нуль нулем. Такие значения существуют для обоих float
и double
типы.
Конечные ненулевые значения типа float
имеют форму s xfa м. xfa 2e, где s +1 или-1, м. является положительным целым числом меньше чем 224, и e является целым числом между-149 и 104, включительно. Самый большой положительный конечный литерал с плавающей точкой типа float
3.40282347e+38F
. Самый маленький положительный ненулевой литерал с плавающей точкой типа float
1.40239846e
-45F
.
Конечные ненулевые значения типа double
имеют форму s xfa м. xfa 2e, где s +1 или-1, м. является положительным целым числом меньше чем 253, и e является целым числом между-1075 и 970, включительно. Самый большой положительный конечный литерал с плавающей точкой типа double
1.79769313486231570e+308
. Самый маленький положительный ненулевой литерал с плавающей точкой типа double
4.94065645841246544e
-324
.
Положительный нуль с плавающей точкой и отрицательный нуль с плавающей точкой сравниваются как равный, но есть другие операции, которые могут отличить их; например, деление 1.0
0.0
производит положительную бесконечность, но деление 1.0
-0.0
производит отрицательную бесконечность.
За исключением НЭН, упорядочиваются значения с плавающей точкой. Когда расположено от самого маленького до самого большого, они - отрицательная бесконечность, отрицательные конечные значения, отрицательный нуль, положительный нуль, положительные конечные значения, и положительная бесконечность.
НЭН неупорядочивают, таким образом, у числовых сравнений есть ложь значения, если или или оба из их операндов НЭН. У теста для числового равенства есть ложь значения, если любым операндом является НЭН, и у теста для количественного неравенства есть истина значения, если любым операндом является НЭН. В частности у теста для числового равенства значения против себя есть ложь значения, если и только если значением является НЭН.
IEEE 754 определяет большое количество отличных значений НЭН, но не в состоянии определить, какие значения НЭН производятся в различных ситуациях. Чтобы избежать проблем мобильности, виртуальная машина Java объединяет эти значения НЭН вместе в единственное концептуальное значение НЭН.
returnAddress
Введите и ОцениваетreturnAddress
тип используется jsr виртуальной машины Java, мочите, и jsr_w инструкции. Значения returnAddress
тип является указателями на коды операций инструкций виртуальной машины Java. В отличие от числовых типов примитивов, returnAddress
тип не соответствует никакому типу данных Java. boolean
Ввестиboolean
введите, виртуальной машине Java не выделяли инструкции операциям на boolean
значения. Вместо этого выражение Java, которое работает на boolean
значения компилируются в использование int
тип данных, чтобы представить boolean
переменные. Хотя у виртуальной машины Java есть поддержка создания массивов типа boolean
(см. описание newarray инструкции), у этого нет выделенной поддержки доступа и изменения элементов boolean
массивы. Массивы типа boolean
получаются доступ и изменил использование byte
инструкции 1 массива
Для получения дополнительной информации по обработке boolean
значения в виртуальной машине Java, см. Главу 7, "Компилирующую для виртуальной машины Java."
reference
типы: типы классов, интерфейсные типы, и типы массива, значения которых являются ссылками на динамически создаваемые экземпляры класса, массивы, или экземпляры класса или массивы та реализация интерфейсы. A reference
значение может также быть специальной нулевой ссылкой, ссылкой ни на какой объект, который будет обозначен здесь null
. null
ссылка первоначально не имеет никакого типа времени выполнения, но может быть брошена к любому типу (§2.4). byte
, char
, short
, int
, float
, reference
, или returnAddress
, или содержать собственный указатель. Два слова являются достаточно большими, чтобы содержать значения больших типов, long
и double
. Области данных времени выполнения Java все определяются с точки зрения этих абстрактных слов. Слово обычно является размером указателя на платформе узла. На 32-разрядной платформе слово составляет 32 бита, указатели составляют 32 бита, и long
s и double
s естественно приводят два слова в рабочее состояние. Наивная 64-разрядная реализация виртуальной машины Java может потратить впустую половину слова, используемого, чтобы сохранить 32-разрядную данную величину, но может также быть в состоянии сохранить все a long
или a double
в одном из этих двух слов, выделенных к этому.
Выбор определенного размера слова, хотя специфичный для платформы, делается на уровне реализации, не как часть проекта виртуальной машины Java. Это не видимо вне реализации или кодировать скомпилированный для виртуальной машины Java.
Всюду по этой книге все ссылки на данную величину слова к этому абстрактному понятию слова.
pc
Регистрpc
(счетчик программы) регистр. В любой точке каждый поток виртуальной машины Java выполняет код единственного метода, текущий метод (§3.6) для того потока. Если тот метод не native
, pc
регистр содержит адрес инструкции виртуальной машины Java, в настоящий момент выполняемой. Если метод, в настоящий момент выполняемый потоком, native
, значение виртуальной машины Java pc
регистр неопределен. Виртуальная машина Java pc
регистр является одним широким словом, ширина, которая, как гарантируют, будет содержать a returnAddress
или собственный указатель на определенной платформе. Спецификация виртуальной машины Java разрешает стекам Java быть или фиксированного или динамически переменного размера. Если стеки Java имеют фиксированный размер, размер каждого стека Java может быть выбран независимо, когда тот стек создается. Реализация виртуальной машины Java может предоставить программисту или контролю за работой пользователей свыше начального размера стеков Java, так же как, в случае динамичного расширения или заключения контракта стеков Java, управления максимальными и минимальными размерами стека Java.
Следующие исключительные условия связываются со стеками Java:
StackOverflowError
.
OutOfMemory
-Error
. -oss
"флаг. Предел размера стека Java может использоваться, чтобы ограничить потребление памяти или поймать безудержные рекурсии. "Куча" Java создается на запуске виртуальной машины. Хранение "кучи" для объектов исправляется автоматической системой управления хранения (обычно сборщик "мусора"); объекты явно никогда не освобождаются. Виртуальная машина Java не принимает определенного типа автоматической системы управления хранения, и метод управления хранением может быть выбран согласно системным требованиям конструктора. "Куча" Java может иметь фиксированный размер, или может быть расширена как требуется вычислением и может быть законтрактована, если большая "куча" становится ненужной. Память для "кучи" Java не должна быть непрерывной.
Реализация виртуальной машины Java может предоставить программисту или контролю за работой пользователей свыше начального размера "кучи", так же как, если "куча" может быть динамически расширена или законтрактована, управление максимальным и минимальным размером "кучи".
Следующее исключительное условие связывается с "кучей" Java:
OutOfMemoryError
. -ms
"и"-mx
"флаги, соответственно. Область метода создается на запуске виртуальной машины. Хотя областью метода является логически часть собранной "мусор" "кучи", простые реализации могут хотеть ни собирать "мусор", ни уплотнять это. Эта версия спецификации виртуальной машины Java не передает под мандат расположение области метода или политик, используемых, чтобы управлять скомпилированным кодом. Область метода может иметь фиксированный размер, или может быть расширена как требуется вычислением и может быть законтрактована, если большая область метода становится ненужной. Память для области метода не должна быть непрерывной.
Реализация виртуальной машины Java может предоставить программисту или контролю за работой пользователей свыше начального размера области метода, так же как, в случае области метода переменного размера, управления максимальным и минимальным размером области метода.
Следующее исключительное условие связывается с областью метода:
OutOfMemoryError
. constant_pool
таблица в Java class
файл (§4.4). Это содержит несколько видов констант, в пределах от числовых литералов, известных во время компиляции методу и полевым ссылкам, которые должны быть разрешены во время выполнения. Постоянный пул служит функции, подобной той из таблицы символов для стандартного языка программирования, хотя это содержит более широкий диапазон данных чем типичная таблица символов. Каждый постоянный пул выделяется от области метода виртуальной машины Java (§3.5.4). Постоянный пул для класса или интерфейса создается когда Java class
файл для класса или интерфейса успешно загружается (§2.16.2) виртуальной машиной Java.
Следующее исключительное условие связывается с созданием постоянного пула для класса или интерфейса:
class
файл, если создание постоянного пула требует большего количества памяти чем, может быть сделан доступным в области метода виртуальной машины Java, виртуальная машина Java бросает OutOfMemoryError
. native
методы, методы, записанные на языках кроме Java. Собственный стек метода может также использоваться, чтобы реализовать эмулятор для набора команд виртуальной машины Java на языке, таком как К. Имплементэйшнс, которые не поддерживают native
методы, и которые самостоятельно не полагаются на стандартные стеки, не должны предоставить собственные стеки метода. Если предоставлено, собственные стеки метода обычно выделяются на на основание потока, когда каждый поток создается. Спецификация виртуальной машины Java разрешает собственным стекам метода быть или фиксированного или динамически переменного размера. Если собственные стеки метода имеют фиксированный размер, размер каждого собственного стека метода может быть выбран независимо, когда тот стек создается. В любом случае реализация виртуальной машины Java может предоставить программисту или контролю за работой пользователей свыше начального размера собственных стеков метода. В случае переменного размера собственные стеки метода это может также сделать доступный элемент управления свыше максимальных и минимальных размеров стека метода.
Следующие исключительные условия связываются со стеками Java:
StackOverflowError
.
Out
OfMemoryError
. -ss
"флаг. Собственный предел размера стека метода может использоваться, чтобы ограничить потребление памяти или поймать безудержные рекурсии в native
методы.Реализация Sun в настоящий момент не проверяет на собственное переполнение стека метода.
Новый фрейм создается каждый раз, когда метод Java вызывается. Фрейм уничтожается, когда его метод завершается, является ли то завершение нормальным или аварийным (выдавая исключение). Фреймы выделяются от стека Java (§3.5.2) потока, создающего фрейм. У каждого фрейма есть свой собственный набор локальных переменных (§3.6.1) и его собственный стек операнда (§3.6.2). Место в памяти для этих структур может быть выделено одновременно, так как размеры области локальной переменной и стека операнда известны во время компиляции, и размер структуры данных фрейма зависит только от реализации виртуальной машины Java.
Только один фрейм, фрейм для выполняющегося метода, является активным в любой точке в данном потоке управления. Этот фрейм упоминается как текущий фрейм, и его метод известен как текущий метод. Класс, в котором определяется текущий метод, является текущим классом. Операции на локальных переменных и стеке операнда всегда в отношении текущего фрейма.
Фрейм прекращает быть текущим, если его метод вызывает другой метод или если его метод завершается. Когда метод вызывается, новый фрейм создается и становится текущим, когда управление передает новому методу. По возврату метода текущий фрейм пасует назад результат своего вызова метода, если таковые вообще имеются, к предыдущему фрейму. Текущий фрейм тогда отбрасывается, поскольку предыдущий фрейм становится текущим. Фреймы Виртуальной машины Java могут естественно думаться как выделяемый на стеке с одним стеком на поток Java (§2.17), но они могут также быть выделенной "кучей".
Отметьте, что фрейм, создаваемый потоком, локален для того потока и не может быть непосредственно сослан никаким другим потоком.
Локальные переменные всегда являются одним широким словом. Две локальные переменные резервируются для каждого long
или double
значение. Эти две локальные переменные адресуются индексом первой из переменных.
Например, локальная переменная с индексом n и содержащий значение типа double
фактически занимает эти два слова в индексах n и n+1 локальной переменной. Виртуальная машина Java не требует, чтобы n был даже. (В интуитивных условиях реализации 64-разрядные значения не должны быть 64-разрядные выровненный в массиве локальных переменных.) Конструкторы свободны решить соответствующий способ разделить 64-разрядное значение данных между двумя локальными переменными.
Например, iadd инструкция добавляет два int
значения вместе. Это требует что int
значения, которые будут добавлены быть лучшими двумя словами стека операнда, продвинутого там предыдущими инструкциями. Оба из int
значения выталкиваются от стека операнда. Они добавляются, и их сумма пододвигается обратно на стек. Подвычисления могут быть вложены на стеке операнда, приводящем к значениям, которые могут использоваться вычислением затрагивания.
Каждая запись на стеке операнда является одним широким словом. Значения типов long
и double
продвигаются на стек операнда как два слова. Виртуальная машина Java не требует, чтобы 64-разрядные значения на стеке операнда были 64-разрядное выровненный. Конструкторы свободны решить соответствующий способ разделить 64-разрядное значение данных между двумя словами стека операнда.
На значения от стека операнда нужно управлять способами, соответствующими их типам. Неправильно, например, продвинуть два int
значения и затем обрабатывают их как a long
, или продвигать два float
значения тогда добавляют их с iadd инструкцией. Небольшое количество инструкций виртуальной машины Java (инструкции дубликата и подкачка) работает на областях данных времени выполнения как необработанные значения данной ширины без отношения, чтобы ввести; эти инструкции не должны использоваться, чтобы разбиться или перестроить слова 64-разрядных данных. Эти ограничения на манипулирование стеком операнда осуществляются, в реализации солнца, class
верификатор файла (§4.9).
class
код файла для метода обращается к методам, которые будут вызваны и переменные, которые будут получены доступ через символьные ссылки. Динамическое подключение преобразовывает эти символьные ссылки метода в конкретные ссылки метода, загружая классы по мере необходимости, чтобы разрешить пока еще неопределенные символы, и преобразовывает переменные доступы в соответствующие смещения в структурах хранения, связанных с расположением времени выполнения этих переменных. Это позднее связывание методов и переменных производит изменения в других классах, которые метод использует менее вероятно, чтобы повредить этот код.
throw
оператор. Если вызов текущего метода обычно завершается, то значение может быть возвращено к методу вызова. Это происходит, когда вызванный метод выполняет одну из инструкций возврата (§3.11.8), выбор которого должен быть подходящим для типа возвращаемого значения (если любой). Фрейм виртуальной машины Java используется в этом случае, чтобы восстановить состояние invoker, включая его локальные переменные и стек операнда, со счетчиком программы invoker, соответственно постепенно увеличенного, чтобы пропустить мимо инструкции вызова метода. Выполнение тогда обычно продолжается во фрейме метода вызова с возвращенным значением (если любой), продвигал на стек операнда того фрейма.
throw
оператор также заставляет исключение быть брошенным и, если исключение не поймано текущим методом, результатами в аварийном завершении метода. Вызов метода, который не завершает неправильно никогда возвраты значение к его invoker. Class
объект, который представляет тип объекта, и другой к памяти, выделенной от "кучи" Java для объектных данных. Другие реализации виртуальной машины Java могут использовать методы, такие как встроенное кэширование, а не таблица метода диспетчеризируют, и они могут или, возможно, не используют дескрипторы.
<init>
. Это имя предоставляется компилятором Java. Поскольку имя <init>
не допустимый идентификатор, он не может использоваться непосредственно программистом Java. Методы инициализации экземпляра могут только быть вызваны в пределах виртуальной машины Java invokespecial инструкцией, и они могут только быть вызваны на неинициализированные экземпляры класса. Метод инициализации экземпляра берет права доступа (§2.7.8) конструктора, из которого он был получен. На уровне виртуальной машины Java, класса или интерфейса инициализируется (§2.16.4), вызывая его класс или интерфейсный метод инициализации без параметров. У метода инициализации класса или интерфейса есть специальное имя <clinit>
. Это имя предоставляется компилятором Java. Поскольку имя <clinit>
не допустимый идентификатор, он не может использоваться непосредственно программистом Java. Класс и интерфейсные методы инициализации вызываются неявно виртуальной машиной Java; они никогда не вызываются непосредственно от кода Java или непосредственно ни от какой инструкции виртуальной машины Java, но только вызываются косвенно как часть процесса инициализации класса.
catch
пункт (§2.15.2) находится, который ловит брошенное значение. Если не такой catch
пункт находится в текущем методе, тогда текущий вызов метода завершается неправильно (§3.6.5). Его стек операнда и локальные переменные отбрасываются, и его фрейм выталкивается, восстанавливая фрейм метода вызова. Исключение тогда повторно бросается в контекст фрейма invoker, и так далее продолжая цепочку вызова метода. Если не подходящий catch
пункт находится прежде, чем вершина цепочки вызова метода достигается, выполнение потока, который выдавал исключение, завершается.
На уровне виртуальной машины Java, каждого catch
пункт описывает диапазон инструкции виртуальной машины Java, для которого это активно, описывает типы исключений, которые это должно обработать, и дает адрес кода, чтобы обработать это. Исключение соответствует a catch
пункт, если инструкция, которая вызвала исключение, находится в соответствующем диапазоне инструкции, и типе исключения, является тем же самым типом как или подкласс класса исключения что catch
дескрипторы пункта. Если соответствие catch
пункт находится, системные ответвления к указанному обработчику. Если никакой обработчик не находится, процесс повторяется до всего вложенного catch
пункты текущего метода были исчерпаны.
Порядок catch
пункты в списке важны. Выполнение виртуальной машины Java продолжается при первом соответствии catch
пункт. Поскольку код Java структурируется, всегда возможно расположить все обработчики исключений для одного метода в единственном списке. Для любого возможного значения счетчика программы этот список может искаться, чтобы найти надлежащий обработчик исключений, то есть, самый внутренний обработчик исключений, который и содержит значение счетчика программы и может обработать выданное исключение.
Если нет никакого соответствия catch
пункт, у текущего метода, как говорят, есть непойманное исключение. Режим выполнения invoker, метод, который вызвал этот метод, восстанавливается. Распространение исключения продолжается, как если бы исключение произошло в invoker в инструкции, которая вызвала метод, фактически повышающий исключение.
Java поддерживает более сложные формы обработки исключений через try-finally
и try-catch-finally
операторы. В таких формах, finally
оператор выполняется даже если никакое соответствие catch
пункт находится. Путем виртуальная машина Java поддерживает реализацию этих форм, обсуждается в Главе 7, "Компилируя для виртуальной машины Java."
class
Формат файлаclass
формат файла. Учитывая цели виртуальной машины Java, определение этого формата файла важно равный его другим компонентам. class
формат файла точно определяет содержание такого файла, включая детали, такие как порядок байтов, который мог бы считаться само собой разумеющимся в специфичном для платформы формате объектных файлов. Глава 4, "Формат файла класса," покрывает class
формат файла подробно.
Игнорируя исключения, внутренний цикл выполнения виртуальной машины Java эффективно
do {
Число и размер дополнительных операндов определяются кодом операции. Если дополнительный операнд составляет больше чем один байт в размере, то это сохранено в байте старшего разряда порядка с обратным порядком байтов сначала. Например, 16-разрядный индекс без знака в локальные переменные сохранен как два байта без знака byte1 и byte2 так, что, его значениеfetch an opcode;
if (operands) fetch operands;
execute the action for the opcode;
} while (there is more to do);
Поток команд байт-кода только однобайтовый выровненный. Эти два исключения являются tableswitch и lookupswitch инструкциями, которые дополняются, чтобы вызвать внутреннее выравнивание некоторых из их операндов на 4-байтовых границах.(
byte1 <<8) |
byte2
Решение ограничить код операции виртуальной машины Java байтом и предшествовать выравниванию данных в пределах скомпилированного кода отражает сознательное смещение в пользу компактности, возможно за счет некоторой производительности в наивных реализациях. Однобайтовый код операции устраняет определенные методы реализации, которые могли улучшить производительность эмулятора виртуальной машины Java, и это ограничивает размер набора команд. Не принятие выравнивания данных означает, что непосредственные данные, больше чем байт, должны быть созданы из байтов во время выполнения на многих машинах.
int
, на стек операнда. fload инструкция делает то же самое с a float
значение. Эти две инструкции могут иметь идентичные реализации, но иметь отличные коды операций. Для большинства введенных инструкций тип инструкции представляется явно в мнемосхеме кода операции буквой: я для int
работа, l для long
, s для short
, b для byte
, c для char
, f для float
, d для double
, и для reference
. У некоторых инструкций, для которых тип однозначен, нет буквы типа в их мнемосхеме. Например, arraylength всегда работает на объекте, который является массивом. Некоторые инструкции, такие как goto, безусловная передача управления, не работают на введенных операндах.
Учитывая однобайтовый размер кода операции виртуальной машины Java, кодирование типов в коды операций оказывает давление на проект его набора команд. Если бы каждая введенная инструкция, поддерживаемая все типы данных времени выполнения виртуальной машины Java, было бы больше инструкций, чем можно было представить в байте. Вместо этого набор команд виртуальной машины Java обеспечивает уменьшенный уровень поддержки типа определенных операций. Другими словами набор команд является преднамеренно не ортогональным. Отдельные инструкции могут использоваться, чтобы преобразовать между неподдерживаемыми и поддерживаемыми типами данных по мере необходимости.
Таблица 3.1 суммирует поддержку типа в наборе команд виртуальной машины Java. Только инструкции, которые существуют для многократных типов, перечисляются. Конкретная инструкция, с информацией о типе, создается, заменяя T в шаблоне инструкции в столбце кода операции буквой в столбце типа. Если столбец типа для некоторого шаблона инструкции и типа является пробелом, то никакая инструкция не существует, поддерживая тот тип работы. Например, есть инструкция загрузки для типа int
, iload, но нет никакой инструкции загрузки для типа byte
.
Отметьте, что у большинства инструкций в Таблице 3.1 нет форм для целочисленных типов byte
, char
, и short
. При записи в ее локальные переменные или стеки операнда, виртуальная машина Java внутренне подписывается - расширяет значения типов byte
и short
вводить int
, и нуль - расширяет значения типа char
вводить int
. Таким образом, большинство операций на значениях типов byte
, char
, и short
правильно выполняются инструкциями, работающими на значениях типа int
. Виртуальная машина Java также обрабатывает значения типа Java boolean
особенно, как отмечено в §3.2.4.
Отображение между типами хранения Java и виртуальной машиной Java computatational типы получается в итоге Таблицей 3.2.
Java (Хранение) Тип | Size in Bits
| Computational Type
|
---|---|---|
byte
| 8 |
int
|
char
| 16 |
int
|
short
| 16 |
int
|
int
| 32 |
int
|
long
| 64 |
long
|
float
| 32 |
float
|
double
| 64 |
double
|
Исключение к этому отображению в случае массивов. Массивы типа boolean
, byte
, char
, и short
может быть непосредственно представлен виртуальной машиной Java. Массивы типа byte
, char
, и short
получаются доступ, используя инструкции, специализированные к тем типам. Массивы типа boolean
получаются доступ, используя byte
инструкции массива.
Остаток от этой главы суммирует набор команд виртуальной машины Java.
Мнемоники команд, показанные выше с запаздывающими буквами между угловыми скобками (например, 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).
Эта нотация для семейств инструкции используется всюду по Спецификации виртуальной машины Java.
byte
, short
, и char
типы (§3.11.1); те операции обрабатываются инструкциями, работающими на типе int
. Целочисленные и инструкции с плавающей точкой также отличаются по их поведению на переполнении, потере значимости, и делятся на нуль. Арифметические инструкции следующие:
Виртуальная машина Java не указывает на переполнение или потерю значимости во время операций на целочисленных типах данных. Единственные целочисленные операции, которые могут выдать исключение, являются целочисленными инструкциями дележа (idiv и ldiv) и целочисленными инструкциями остатка (irem и lrem), которые бросают ArithmeticException
если делитель является нулем.
Операции Виртуальной машины Java на числах с плавающей точкой ведут себя точно как определено в IEEE 754. В частности виртуальная машина Java требует полной поддержки IEEE 754 денормализованные числа с плавающей точкой и постепенная потеря значимости, которые облегчают доказывать требуемые свойства определенных числовых алгоритмов.
Виртуальная машина Java требует, чтобы арифметика с плавающей точкой вела себя как будто каждый оператор с плавающей точкой, округленный ее результат с плавающей точкой к точности результата. Неточные результаты должны быть округлены к представимому значению, самому близкому к бесконечно точному результату; если два самых близких представимых значения одинаково рядом, тот с его младшим значащим разрядным нулем выбирается. Это - значение по умолчанию стандарта IEEE 754 округление режима, известного как раунд-к-самому-близкому.
Виртуальная машина Java использует раунд к нулю, преобразовывая значение с плавающей точкой в целое число. Это приводит к числу, являющемуся усеченным; отбрасываются любые биты мантиссы, которые представляют дробную часть значения операнда. Раунд к нулю выбирает как его результат значение типа, самое близкое к, но не больше в величине чем, бесконечно точный результат.
Операторы виртуальной машины Java с плавающей точкой не производят исключений. Работа, которая переполнения производят бесконечность со знаком, работа, которая потери значимости производят нуль со знаком, и работа, у которой нет никакого математически определенного результата, производит НЭН. Все числовые операции с НЭН как операнд производят НЭН в результате.
Виртуальная машина Java непосредственно поддерживает следующие расширяющиеся числовые преобразования, подмножество расширения Java примитивные преобразования (§2.6.2):
Расширяющиеся числовые инструкции преобразования являются i2l, i2f, i2d, l2f, l2d, и f2d. Мнемоника для этих кодов операций прямая данный соглашения о присвоении имен для введенных инструкций и каламбурящего использования 2, чтобы значить "для". Например, i2d инструкция преобразовывает
int
оцените a double
. Расширяющиеся числовые преобразования не теряют информацию о полной величине числового значения. Действительно, преобразования, расширяющиеся от int
введите к long
введите и от float
к double
не теряйте информацию вообще; числовое значение сохраняется точно. Преобразование int
или a long
значение к float
, или a long
значение к double
, может потерять точность, то есть, может потерять некоторые из младших значащих битов значения; получающееся значение с плавающей точкой является правильно округленной версией целочисленного значения, используя режим раунда-к-самому-близкому IEEE 754.
Согласно этому правилу, расширяющемуся числовому преобразованию int
к a long
просто знак - расширяет two's-дополнительное представление int
значение, чтобы заполнить более широкий формат. Расширяющееся числовое преобразование a char
к нулю целочисленного типа - расширяет представление char
значение, чтобы заполнить более широкий формат.
Несмотря на то, что потеря точности может произойти, расширяя числовые преобразования никогда не приводит к исключению на этапе выполнения.
Отметьте, что расширяющиеся числовые преобразования не существуют от целочисленных типов byte
, char
, и short
вводить int
. Как отмечено в §3.11.1, значениях типа byte
, char
, и short
внутренне расширяются до типа int
, создание этих неявных преобразований.
Виртуальная машина Java также непосредственно поддерживает следующие сужающиеся числовые преобразования, подмножество сужения Java примитивные преобразования (§2.6.3):
Сужающиеся числовые инструкции преобразования являются i2b, i2c, i2s, l2i, f2i, f2l, d2i, d2l, и d2f. Сужающееся числовое преобразование может привести к значению различного знака, или различного порядка величины, или обоих; они могут, таким образом, потерять точность.
Сужающееся числовое преобразование int
или long
к целочисленному типу T просто отбрасывает все кроме битов самых низкоуровневых N, где N является числом битов, используемых, чтобы представить тип T. Это может заставить получающееся значение не иметь тот же самый знак как входное значение.
В сужающемся числовом преобразовании значения с плавающей точкой к целочисленному типу T, где T также int
или long
, значение с плавающей точкой преобразовывается в тип T следующим образом:
int
или long
0
.
long
и это целочисленное значение может быть представлено как a long
, тогда результат long
значение V.
int
и это целочисленное значение может быть представлено как int
, тогда результат int
значение V.
int
или long
.
int
или long
. double
к float
ведет себя в соответствии с IEEE 754. Результат правильно округляется, используя режим раунда-к-самому-близкому IEEE 754. Значение, слишком маленькое, чтобы быть представленным как a float
преобразовывается в положительный или отрицательный нуль типа float
; значение, слишком большое, чтобы быть представленным как a float
преобразовывается в положительную или отрицательную бесконечность. A double
НЭН всегда преобразовывается в a float
НЭН.Несмотря на то, что переполнение, потеря значимости, или потеря точности могут произойти, сужая преобразования среди числовых типов никогда не приводит к исключению на этапе выполнения.
static
поля, известные как переменные класса) и поля экземпляров класса (не -static
поля, известные как переменные экземпляра): getfield, putfield, getstatic, putstatic.
int
, long
, float
, double
, и reference
типы. Сравнение с данными byte
, char
, и short
типы делаются, используя int
инструкция сравнения (§3.11.1). Из-за этого включенного акцента int
сравнения, виртуальная машина Java включает большее дополнение команд условного перехода для типа int
чем для других типов. У виртуальной машины Java есть отличные команды условного перехода, которые тестируют на нулевую ссылку, и таким образом не обязан определять конкретное значение для null
(§3.3).
Все int
и long
условные инструкции передачи управления выполняют подписанные сравнения. Сравнение с плавающей точкой выполняется в соответствии с IEEE 754.
<init>
, a private
метод, или метод суперкласса: invokespecial.
static
) метод в именованном классе: invokestatic. byte
, char
, short
, или int
), lreturn, freturn, dreturn, и areturn. Кроме того, инструкция возврата используется, чтобы возвратиться из методов, которые, как объявляют, были void
. finally
finally
ключевое слово использует jsr, jsr_w, и мочите инструкции. См. Раздел 4.9.6, "Исключения и наконец" и Раздел 7.13, "Компилируя наконец."
class
формат файла и набор команд. Эти компоненты жизненно важны для платформы - и независимость реализации виртуальной машины Java. Конструктор может предпочесть думать о них как о средстве надежно передать фрагменты программ между двумя платформами, а не как проект, который будет сопровождаться точно. Важно понять, где строка между общедоступным проектом и частной реализацией находится. Виртуальная машина Java должна быть в состоянии читать class
файлы, и это должно точно реализовать семантику кода виртуальной машины Java там. Один способ сделать это состоит в том, чтобы взять этот документ в качестве спецификации и реализовывать ту спецификацию буквально. Но это является также совершенно выполнимым и требуемым для конструктора, чтобы изменить или оптимизировать реализацию в пределах ограничений этой спецификации. Пока class
формат файла может быть считан, и семантика его кода сохраняется, конструктор может реализовать их семантика всегда. То, что "под капотом", является бизнесом конструктора, пока корректный внешний интерфейс тщательно сохраняется 2
Конструктор может использовать эту гибкость, чтобы адаптировать реализации виртуальной машины Java для высокой производительности, низкое использование памяти, или мобильность. То, что имеет смысл в данной реализации, зависит от целей той реализации. Диапазон опций реализации включает следующее:
class
верификатор файла; см. Раздел 4.9, "Проверка Файлов класса").
boolean
массивы эффективно byte
массивы, используя элемент 8 битов за булевскую переменную.2 есть некоторые исключения: отладчики и генераторы кода JIT могут потребовать доступа к элементам виртуальной машины Java, которые, как обычно полагают, являются "под капотом." Sun работает с другими конструкторами виртуальной машины Java и поставщиками инструментов, чтобы стандартизировать интерфейсы к виртуальной машине Java для использования такими инструментами.
Содержание | Предыдущий | Следующий | Индекс
Спецификация Виртуальной машины Java
Авторское право © 1996, 1997 Sun Microsystems, Inc. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления к jvm@java.sun.com