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


ГЛАВА 4

Формат файла класса


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

A class файл состоит из потока 8-разрядных байтов. Все 16-разрядные, 32-разрядные, и 64-разрядные количества создаются, читая в два, четыре, и восемь последовательных 8-разрядных байтов, соответственно. Многобайтовые элементы данных всегда сохранены в порядке с обратным порядком байтов, где высокие байты на первом месте. В Java этот формат поддерживается интерфейсами java.io.DataInput и java.io.DataOutput и классы такой как java.io.DataInputStream и java.io.DataOutputStream.

Эта глава определяет свой собственный набор типов данных, представляющих Java class данные файла: типы u1, u2, и u4 представьте без знака - два - или четырехбайтовое количество, соответственно. В Java эти типы могут быть считаны методами такой как readUnsignedByte, readUnsignedShort, и readInt из интерфейса java.io.DataInput.

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

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

Где мы именуем структуру данных как массив, это - буквально массив.


4.1 ClassFile

A class файл содержит сингл ClassFile структура:


    ClassFile {
    	u4 magic;
    	u2 minor_version;
    	u2 major_version;
    	u2 constant_pool_count;
    	cp_info constant_pool[constant_pool_count-1];
    	u2 access_flags;
    	u2 this_class;
    	u2 super_class;
    	u2 interfaces_count;
    	u2 interfaces[interfaces_count];
    	u2 fields_count;
    	field_info fields[fields_count];
    	u2 methods_count;
    	method_info methods[methods_count];
    	u2 attributes_count;
    	attribute_info attributes[attributes_count];
    }

Элементы в ClassFile структура следующие:

    волшебство

magic элемент предоставляет магическое число, идентифицирующее class формат файла; у этого есть значение 0xCAFEBABE.

    minor_version, major_version
Значения minor_version и major_version элементы являются номерами вспомогательной версии и номерами основной версии компилятора, который произвел это class файл. Реализация виртуальной машины Java обычно поддерживает class файлы, имеющие данный номер основной версии и номера вспомогательной версии 0 через некоторую деталь minor_version.

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

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

В Наборе Разработчика Java Sun (JDK) 1.0.2 выпуска, задокументированные этой книгой, значением major_version 45. Значение minor_version 3. Только Sun может определить значение новых class номера версий файла.

    constant_pool_count
Значение constant_pool_count элемент должен быть больше чем нуль. Это подает число записей constant_pool таблица class файл, где constant_pool запись в индексном нуле включается в количество, но не присутствует в constant_pool таблица файла класса. A constant_pool индекс считают допустимым, если это больше чем нуль и меньше чем constant_pool_count.

    constant_pool []
constant_pool таблица структур переменной длины (§4.4) представление различных строковых констант, имен классов, имен полей, и других констант, которые упоминаются в пределах ClassFile структура и ее подструктуры.

Первая запись constant_pool таблица, constant_pool[0], резервируется для внутреннего пользования реализацией виртуальной машины Java. Та запись не присутствует в class файл. Первая запись в class файл constant_pool[1].

Каждый из constant_pool записи таблицы в индексах 1 через constant_pool_count-1 структура переменной длины (§4.4), чей формат обозначается его первым байтом "тега".

    access_flags
Значение access_flags элемент является маской модификаторов, используемых с классом и интерфейсными объявлениями. access_flags модификаторы показывают в Таблице 4.1.

Имя флага Значение Значение Используемый
ACC_PUBLIC 0x0001 Общедоступно; может быть получен доступ снаружи его пакета. Класс, интерфейс
ACC_FINAL 0x0010 Является заключительным; никакие подклассы не позволяются. Класс
ACC_SUPER 0x0020 Методы суперкласса обработки особенно в invokespecial. Класс, интерфейс
ACC_INTERFACE 0x0200 Интерфейс. Интерфейс
ACC_ABSTRACT 0x0400 Абстрактно; возможно, не инстанцируется. Класс, интерфейс


Интерфейс отличает ACC_INTERFACE устанавливаемый флаг. Если ACC_INTERFACE не устанавливается, этот файл класса определяет класс, не интерфейс.

Интерфейсы могут только использовать флаги, обозначенные в Таблице 4.1 как использующийся интерфейсами. Классы могут только использовать флаги, обозначенные в Таблице 4.1 как использующийся классами. Интерфейс неявно abstract (§2.13.1); ACC_ABSTRACT флаг должен быть установлен. Интерфейс не может быть final; его реализация никогда не могла завершаться (§2.13.1), если бы это было, таким образом, у этого не могло быть ACC_FINAL флаг устанавливается.

Флаги ACC_FINAL и ACC_ABSTRACT не может оба быть установлен для класса; реализация такого класса никогда не могла завершаться (§2.8.2).

Установка ACC_SUPER флаг направляет виртуальную машину Java который из двух альтернативных семантик для ее invokespecial инструкции, чтобы выразить; это существует для обратной совместимости для кода, скомпилированного более старыми компиляторами Java Sun. Все новые реализации виртуальной машины Java должны реализовать семантику для invokespecial, задокументированного в Главу 6, "Набор команд виртуальной машины Java." Все новые компиляторы к набору команд виртуальной машины Java должны установить ACC_SUPER флаг. Более старые компиляторы Java Sun генерируют ClassFile флаги с ACC_SUPER сброс. Более старые реализации виртуальной машины Java Sun игнорируют флаг, если он устанавливается.

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

    this_class
Значение this_class элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Class_info (§4.4.1) структура, представляющая класс или интерфейс, определяется этим class файл.

    super_class
Для класса, значения super_class элемент или должен быть нулем или должен быть допустимым индексом в constant_pool таблица. Если значение super_class элемент является ненулевым, constant_pool запись по тому индексу должна быть a CONSTANT_Class_info (§4.4.1) структура, представляющая суперкласс класса, определяется этим class файл. Ни суперкласс, ни любой из его суперклассов не могут быть a final класс.

Если значение super_class нуль, тогда это class файл должен представить класс java.lang.Object, единственный класс или интерфейс без суперкласса.

Для интерфейса, значения super_class должен всегда быть допустимый индекс в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Class_info структура, представляющая класс java.lang.Object.

    interfaces_count
Значение interfaces_count элемент дает число прямых суперинтерфейсов этого класса или интерфейсного типа.

    интерфейсы []
Каждое значение в interfaces массив должен быть допустимым индексом в constant_pool таблица. constant_pool запись в каждом значении interfaces[я], где 0 < I £ interfaces_count, должен быть a CONSTANT_Class_info структура (§4.4.1), представляющая интерфейс, который является прямым суперинтерфейсом этого класса или интерфейсного типа, в слева направо порядок, данный в источнике для типа.

    fields_count
Значение fields_count элемент дает число field_info структуры в fields таблица. field_info (§4.5) структуры представляют все поля, и переменные класса и переменные экземпляра, объявленные этим классом или интерфейсным типом.

    поля []
Каждое значение в fields таблица должна быть переменной длиной field_info (§4.5) структура, дающая полное описание поля в классе или интерфейсном типе. fields таблица включает только те поля, которые объявляются этим классом или интерфейсом. Это не включает поля представления элементов, которые наследованы от суперклассов или суперинтерфейсов.

    methods_count
Значение methods_count элемент дает число method_info структуры в methods таблица.

    методы []
Каждое значение в methods таблица должна быть переменной длиной method_info (§4.6) структура, дающая полное описание и виртуальную машину Java, кодируют для метода в классе или интерфейсе.

method_info структуры представляют все методы, оба метода экземпляра и, для классов, класс (static) методы, объявленные этим классом или интерфейсным типом. methods таблица только включает те методы, которые явно объявляются этим классом. У интерфейсов есть только единственный метод <clinit>, интерфейсный метод инициализации (§3.8). methods таблица не включает методы представления элементов, которые наследованы от суперклассов или суперинтерфейсов.

    attributes_count
Значение attributes_count элемент дает число атрибутов (§4.7) в attributes таблица этого класса.

    атрибуты []
Каждое значение attributes таблица должна быть структурой атрибута переменной длины. A ClassFile у структуры может быть любое число атрибутов (§4.7) связанный с этим.

Единственный атрибут, определенный этой спецификацией для attributes таблица a ClassFile структура SourceFile атрибут (§4.7.2).

Реализация виртуальной машины Java обязана тихо игнорировать любые атрибуты в attributes таблица a ClassFile структура, которую это не распознает. Атрибутам, не определенным в этой спецификации, не позволяют влиять на семантику class файл, но только предоставить дополнительную дескриптивную информацию (§4.7.1).


4.2 Внутренняя Форма Полностью определенных Имен классов

Имена классов, которые появляются в class файловые структуры всегда представляются в полностью определенной форме (§2.7.9). Эти имена классов всегда представляются как CONSTANT_Utf8_info (§4.4.7) структуры, и на них ссылаются от тех CONSTANT_NameAndType_info структуры (§4.4.6), у которых есть имена классов как часть их дескриптора (§4.3), так же как от всех CONSTANT_Class_info (§4.4.1) структуры.

По историческим причинам точный синтаксис полностью определенных имен классов, которые появляются в class файловые структуры отличаются от знакомого Java полностью определенное имя класса, задокументированное в §2.7.9. Во внутренней форме, периоды ASCII ('.') это обычно разделяет идентификаторы (§2.2), которые составляют полностью определенное имя, заменяются наклонными чертами вправо ASCII ('/'). Например, нормальное полностью определенное имя класса Thread java.lang.Thread. В форме, используемой в дескрипторах в class файлы, ссылка на имя класса Thread реализуется, используя a CONSTANT_Utf8_info структура, представляющая строку "java/lang/Thread".


4.3 Дескрипторы

Дескриптор является строкой, представляющей тип поля или метода.

4.3.1 Нотация грамматики

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

4.3.2 Полевые Дескрипторы

Полевой дескриптор представляет тип класса или переменной экземпляра. Это - серия символов, сгенерированных грамматикой:

    FieldDescriptor:

FieldType

    ComponentType:

FieldType

    FieldType:

BaseType

ObjectType

ArrayType

    BaseType:

B

C

D

F

Я

J

S

Z

    ObjectType:
L <имя класса>;

    ArrayType:
[ComponentType

Символы BaseType, L и; из ObjectType, и [ArrayType все символы ASCII. <Имя класса> представляет полностью определенное имя класса, например, java.lang.Thread. По историческим причинам это сохранено в a class файл в измененной внутренней форме (§4.2).

Значение типов поля следующие:


 B	      byte			signed byte 
C char character
D double double-precision IEEE 754 float
F float single-precision IEEE 754 float
I int integer
J long long integer
L<classname>; ... an instance of the class
S short signed short
Z boolean true or false
[ ... one array dimension


Например, дескриптор int переменная экземпляра - просто я. Дескриптор переменной экземпляра типа Object Ljava/lang/Object;. Отметьте что внутренняя форма полностью определенного имени класса для класса Object используется. Дескриптор переменной экземпляра, которая является многомерным double массив,

    double d[][][];

    [[[D

4.3.3 Дескрипторы метода

Дескриптор параметра представляет параметр, который передают методу:

    ParameterDescriptor:

FieldType

Дескриптор метода представляет параметры, которые метод берет и значение, которое это возвращает:

    MethodDescriptor:

(ParameterDescriptor *) ReturnDescriptor

Дескриптор возврата представляет возвращаемое значение от метода. Это - серия символов, сгенерированных грамматикой:

    ReturnDescriptor:

FieldType

V

Символ V указывает, что метод не возвращает значения (его тип возврата void). Иначе, дескриптор указывает на тип возвращаемого значения.

Допустимый дескриптор метода Java должен представить 255 или меньше слов параметров метода, где тот предел включает слово для this в случае вызовов метода экземпляра. Предел находится на числе слов параметров метода а не на числе параметров непосредственно; параметры типа long и double каждое использование два слова.

Например, дескриптор метода для метода

    Object mymethod(int i, double d, Thread t)

    (IDLjava/lang/Thread;)Ljava/lang/Object;
Отметьте что внутренние формы полностью определенных имен классов Thread и Object используются в дескрипторе метода.

Дескриптор метода для mymethod то же самое ли mymethod static или метод экземпляра. Хотя метод экземпляра передают this, ссылка на текущий экземпляр класса, в дополнение к его намеченным параметрам, тот факт не отражается в дескрипторе метода. (Ссылка на this не передается к a static метод.) Ссылка на this передается неявно инструкциями вызова метода виртуальной машины Java, используемой, чтобы вызвать методы экземпляра.


4.4 Постоянный Пул

Все constant_pool у записей таблицы есть следующий общий формат:


    cp_info {
    	u1 tag;
    	u1 info[];
    }

Каждый элемент в constant_pool таблица должна начаться с 1-байтового тега, указывающего отчасти cp_info запись. Содержание info массив меняется в зависимости от значения tag. Допустимые теги и их значения перечисляются в Таблице 4.2

Постоянный Тип Значение
CONSTANT_Class 7
CONSTANT_Fieldref 9
CONSTANT_Methodref 10
CONSTANT_InterfaceMethodref 11
CONSTANT_String 8
CONSTANT_Integer 3
CONSTANT_Float 4
CONSTANT_Long 5
CONSTANT_Double 6
CONSTANT_NameAndType 12
CONSTANT_Utf8 1


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

4.4.1 CONSTANT_Class

CONSTANT_Class_info структура используется, чтобы представить класс или интерфейс:


    CONSTANT_Class_info {
    	u1 tag;
    	u2 name_index;
    }

Элементы CONSTANT_Class_info структура является следующим:

    тег

tag у элемента есть значение CONSTANT_Class (7).

    name_index
Значение name_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Utf8_info структура (§4.4.7), представляющая допустимое полностью определенное имя класса Java (§2.8.1), который был преобразован в class внутренняя форма файла (§4.2).

Поскольку массивы являются объектами, коды операций anewarray и multianewarray могут сослаться на массив "классы" через CONSTANT_Class_info (§4.4.1) структуры в constant_pool таблица. В этом случае имя класса является дескриптором типа массива. Например, имя класса, представляющее двумерное int тип массива;

    int[][] 

    [[I
Имя класса, представляющее массив типа класса Thread;

    Thread[] 

    [Ljava.lang.Thread;
У допустимого дескриптора типа массива Java должно быть 255 или меньше размерностей массива.

4.4.2 CONSTANT_Fieldref, CONSTANT_Methodref, и CONSTANT_InterfaceMethodref

Поля, методы, и интерфейсные методы представляются подобными структурами:


    CONSTANT_Fieldref_info {
    	u1 tag;
    	u2 class_index;
    	u2 name_and_type_index;
    }


    CONSTANT_Methodref_info {      u1 tag;      u2 class_index;      u2 name_and_type_index;     }

    CONSTANT_InterfaceMethodref_info {      u1 tag;      u2 class_index;      u2 name_and_type_index;     }
Элементы этих структур следующие:

    тег

tag элемент a CONSTANT_Fieldref_info у структуры есть значение CONSTANT_Fieldref (9).

tag элемент a CONSTANT_Methodref_info у структуры есть значение CONSTANT_Methodref (10).

tag элемент a CONSTANT_InterfaceMethodref_info у структуры есть значение CONSTANT_InterfaceMethodref (11).

    class_index
Значение class_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Class_info структура (§4.4.1), представляющая класс или интерфейсный тип, который содержит объявление поля или метода.

class_index элемент a CONSTANT_Fieldref_info или a CONSTANT_Methodref_info структура должна быть типом класса, не интерфейсным типом. class_index элемент a CONSTANT_InterfaceMethodref_info структура должна быть интерфейсным типом, который объявляет данный метод.

    name_and_type_index
Значение name_and_type_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_NameAndType_info (§4.4.6) структура. Это constant_pool запись указывает на имя и дескриптор поля или метода.

Если имя метода a CONSTANT_Methodref_info или CONSTANT_InterfaceMethodref_info начинается с a '<' ('u003c'), тогда имя должно быть одним из специальных внутренних методов (§3.8), также <init> или <clinit>. В этом случае метод не должен возвратить значение.

4.4.3 CONSTANT_String

CONSTANT_String_info структура используется, чтобы представить постоянные объекты типа java.lang.String:


    CONSTANT_String_info {
    	u1 tag;
    	u2 string_index;
    }

Элементы CONSTANT_String_info структура следующие:

    тег

tag элемент CONSTANT_String_info у структуры есть значение CONSTANT_String (8).

    string_index
Значение string_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Utf8_info (§4.4.3) тех, структура, представляющая последовательность символов, к который java.lang.String объект состоит в том, чтобы быть инициализирован.

4.4.4 CONSTANT_Integer и CONSTANT_Float

CONSTANT_Integer_info и CONSTANT_Float_info структуры представляют числовые четыре байта (int и float) константы:


    CONSTANT_Integer_info {
    	u1 tag;
    	u4 bytes;
    }


    CONSTANT_Float_info {      u1 tag;      u4 bytes;     }
Элементы этих структур следующие:

    тег

tag элемент CONSTANT_Integer_info у структуры есть значение CONSTANT_Integer (3).

tag элемент CONSTANT_Float_info у структуры есть значение CONSTANT_Float (4).

    байты
bytes элемент CONSTANT_Integer_info структура содержит значение int постоянный. Байты значения сохранены в обратном порядке байтов (высокий байт сначала) порядок.

bytes элемент CONSTANT_Float_info структура содержит значение float постоянный в IEEE 754 "единственный формат с плавающей точкой" разрядное расположение. Байты значения сохранены в обратном порядке байтов (высокий байт сначала) порядок, и сначала преобразовываются в int параметр. Затем:

    int s = ((bytes >> 31) == 0) ? 1 : -1;
    int e = ((bytes >> 23) & 0xff);
    int m = (e == 0) ?
    		(bytes & 0x7fffff) << 1 :
    		(bytes & 0x7fffff) | 0x800000;
Затем float значение равняется результату математического выражения



.

4.4.5 CONSTANT_Long и CONSTANT_Double

CONSTANT_Long_info и CONSTANT_Double_info представьте числовые восемь байтов (long и double) константы:


    CONSTANT_Long_info {
    	u1 tag;
    	u4 high_bytes;
    	u4 low_bytes;
    }


    CONSTANT_Double_info {      u1 tag;      u4 high_bytes;      u4 low_bytes;     }
Все восьмибайтовые константы приводят две записи в рабочее состояние в constant_pool таблица class файл, так же как в версии в памяти постоянного пула, который создается когда a class файл читается. Если a CONSTANT_Long_info или CONSTANT_Double_info структура является элементом в constant_pool таблица по индексу n, тогда следующий допустимый элемент в пуле располагается по индексу n+2. constant_pool индекс n+1 нужно считать недопустимым и не должен использоваться 1

Элементы этих структур следующие:

    тег

tag элемент CONSTANT_Long_info у структуры есть значение CONSTANT_Long (5).

tag элемент CONSTANT_Double_info у структуры есть значение CONSTANT_Double (6).

    high_bytes, low_bytes
Без знака high_bytes и low_bytes элементы CONSTANT_Long структура вместе содержит значение long постоянный ((long)high_bytes << 32) + low_bytes, где байты каждого из high_bytes и low_bytes сохранены в обратном порядке байтов (высокий байт сначала) порядок.

high_bytes и low_bytes элементы CONSTANT_Double_info структура содержит double значение в IEEE 754 "двойной формат с плавающей точкой" разрядное расположение. Байты каждого элемента сохранены в обратном порядке байтов (высокий байт сначала) порядок. high_bytes и low_bytes элементы сначала преобразовываются в a long параметр. Затем:

    int s = ((bits >> 63) == 0) ? 1 : -1;
    int e = (int)((bits >> 52) & 0x7ffL);
    long m = (e == 0) ?
    	(bits & 0xfffffffffffffL) << 1 :
    	(bits & 0xfffffffffffffL) | 0x10000000000000L;
Затем значение с плавающей точкой равняется double значение математического выражения



.

4.4.6 CONSTANT_NameAndType

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


    CONSTANT_NameAndType_info {
    	u1 tag;
    	u2 name_index;
    	u2 descriptor_index;
    }

Элементы CONSTANT_NameAndType_info структура следующие:

    тег

tag элемент CONSTANT_NameAndType_info у структуры есть значение CONSTANT_NameAndType (12).

    name_index
Значение name_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Utf8_info (§4.4.7) структура, представляющая допустимое имя поля Java или имя метода (§2.7) сохраненный как простое (не полностью определенный) имя (§2.7.1), то есть, как идентификатор Java.

    descriptor_index
Значение descriptor_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Utf8_info (§4.4.7) структура, представляющая допустимый полевой дескриптор Java (§4.3.2) или дескриптор метода (§4.3.3).

4.4.7 CONSTANT_Utf8

CONSTANT_Utf8_info структура используется, чтобы представить постоянные строковые значения.

Строки UTF-8 кодируются так, чтобы символьные последовательности, которые содержат только ненулевые символы ASCII, могли быть представлены, используя только один байт за символ, но символы до 16 битов могут быть представлены. Все символы в диапазоне 'u0001' к 'u007F' представляются единственным байтом:

0 биты 0-7


Семь битов данных в байте дают значение представленного символа. Нулевой символ ('u0000') и символы в диапазоне 'u0080' к 'u07FF' представляются парой байтов x и y:

x: 1 1 0 биты 6-10 y: 1 0 биты 0-5


Байты представляют символ со значением ((x & 0x1f) << 6) + (y & 0x3f).

Символы в диапазоне 'u0800' к 'uFFFF' представляются на три байта x, y, и z:

x: 1 1 1 0 биты 12-15 y: 1 0 биты 6-11 z: 1 0 биты 0-5


Символ со значением ((x & 0xf) << 12) + ((y & 0x3f) << 6) + (z & 0x3f) представляется байтами.

Байты многобайтовых символов сохранены в class файл в обратном порядке байтов (высокий байт сначала) порядок.

Есть два различия между этим форматом и "стандартным" форматом UTF-8. Во-первых, нулевой байт (byte)0 кодируется, используя двухбайтовый формат, а не однобайтовый формат, так, чтобы виртуальная машина Java, которую никогда не встраивали строки UTF-8, обнулила. Во-вторых, только однобайтовое, два байта, и трехбайтовые форматы используются. Виртуальная машина Java не распознает дольше форматы UTF-8.

Для получения дополнительной информации относительно формата UTF-8, см. Файловую систему Безопасный Формат Преобразования UCS (FSS_UTF), X/Open Предварительная Спецификация, X/Open Company Ltd., Номер документа: P316. Эта информация также появляется в ISO/IEC 10646, Приложении P.

CONSTANT_Utf8_info структура


    CONSTANT_Utf8_info {
    	u1 tag;
    	u2 length;
    	u1 bytes[length];
    }

Элементы CONSTANT_Utf8_info структура является следующим:

    тег

tag элемент CONSTANT_Utf8_info у структуры есть значение CONSTANT_Utf8 (1).

    длина
Значение length элемент подает число байтов bytes массив (не длина получающейся строки). Строки в CONSTANT_Utf8_info структура не завершается нулем.

    байты []
bytes массив содержит байты строки. Ни у какого байта не может быть значения (byte)0 или (byte)0xf0-(byte)0xff.


4.5 Поля

Каждое поле описывается переменной длиной field_info структура. Формат этой структуры


    field_info {
    	u2 access_flags;
    	u2 name_index;
    	u2 descriptor_index;
    	u2 attributes_count;
    	attribute_info attributes[attributes_count];
    }

Элементы field_info структура следующие:

    access_flags

Значение access_flags элемент является маской модификаторов, используемых, чтобы описать право доступа к и свойства поля. access_flags модификаторы показывают в Таблице 4.3.

Имя флага Значение Значение Используемый
ACC_PUBLIC 0x0001 public; может быть получен доступ снаружи его пакета. Любое поле
ACC_PRIVATE 0x0002 private; применимый только в пределах класса определения. Поле класса
ACC_PROTECTED 0x0004 protected; может быть получен доступ в пределах подклассов. Поле класса
ACC_STATIC 0x0008 static. Любое поле
ACC_FINAL 0x0010 final; никакое дальнейшее переопределение или присвоение после инициализации. Любое поле
ACC_VOLATILE 0x0040 volatile; не может кэшироваться. Поле класса
ACC_TRANSIENT 0x0080 transient; не записанный или читают персистентным диспетчером объектов. Поле класса


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

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

У полей класса может быть самое большее один из флагов ACC_PUBLIC, ACC_PROTECTED, и ACC_PRIVATE набор (§2.7.8). У поля класса, возможно, нет обоих ACC_FINAL и ACC_VOLATILE набор (§2.9.1).

Каждое интерфейсное поле неявно static и final (у §2.13.4) и должны быть оба ACC_STATIC и ACC_FINAL флаги устанавливаются. Каждое интерфейсное поле неявно public (у §2.13.4) и должен быть ACC_PUBLIC флаг устанавливается.

    name_index
Значение name_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Utf8_info структура (§4.4.7), которая должна представить допустимое имя поля Java (§2.7) сохраненный как простое (не полностью определенный) имя (§2.7.1), то есть, как идентификатор Java.

    descriptor_index
Значение descriptor_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Utf8 структура (§4.4.7), которая должна представить допустимый полевой дескриптор Java (§4.3.2).

    attributes_count
Значение attributes_count элемент указывает на число дополнительных атрибутов (§4.7) этого поля.

    атрибуты []
Каждое значение attributes таблица должна быть структурой атрибута переменной длины. У поля может быть любое число атрибутов (§4.7) связанный с этим.

Единственный атрибут, определенный для attributes таблица a field_info структура этой спецификацией ConstantValue атрибут (§4.7.3).

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


4.6 Методы

Каждый метод, и каждый метод инициализации экземпляра <init>, описывается переменной длиной method_info структура. У структуры есть следующий формат:


    method_info {
    	u2 access_flags;
    	u2 name_index;
    	u2 descriptor_index;
    	u2 attributes_count;
    	attribute_info attributes[attributes_count];
    }

Элементы method_info структура следующие:

    access_flags

Значение access_flags элемент является маской модификаторов, используемых, чтобы описать право доступа к и свойства метода или метода инициализации экземпляра (§3.8). access_flags модификаторы показывают в Таблице 4.4.

Имя флага Значение Значение Используемый
ACC_PUBLIC 0x0001 public; может быть получен доступ снаружи его пакета. Любой метод
ACC_PRIVATE 0x0002 private; применимый только в пределах класса определения. Класс/метод экземпляра
ACC_PROTECTED 0x0004 protected; может быть получен доступ в пределах подклассов. Класс/метод экземпляра
ACC_STATIC 0x0008 static. Класс/метод экземпляра
ACC_FINAL 0x0010 final; никакое переопределение не позволяется. Класс/метод экземпляра
ACC_SYNCHRONIZED 0x0020 synchronized; оберните использование в блокировку монитора. Класс/метод экземпляра
ACC_NATIVE 0x0100 native; реализованный на языке кроме Java. Класс/метод экземпляра
ACC_ABSTRACT 0x0400 abstract; никакая реализация не обеспечивается. Любой метод


Методы в интерфейсах могут только использовать флаги, обозначенные в Таблице 4.4 как использующийся любым методом. Класс и методы экземпляра (§2.10.3) могут использовать любой из флагов в Таблице 4.4. Методы инициализации экземпляра (§3.8) могут только использовать ACC_PUBLIC, ACC_PROTECTED, и ACC_PRIVATE.

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

Самое большее один из флагов ACC_PUBLIC, ACC_PROTECTED, и ACC_PRIVATE может быть установлен для любого метода. Класс и методы экземпляра, возможно, не используют ACC_ABSTRACT вместе с ACC_FINAL, ACC_NATIVE, или ACC_SYNCHRONIZED (то есть, native и synchronized методы требуют реализации). Класс или метод экземпляра, возможно, не используют ACC_PRIVATE с ACC_ABSTRACT (то есть, a private метод не может быть переопределен, таким образом, такой метод никогда не мог реализовываться или использоваться). Класс или метод экземпляра, возможно, не используют ACC_STATIC с ACC_ABSTRACT (то есть, a static метод неявно final и таким образом не может быть переопределен, таким образом, такой метод никогда не мог реализовываться или использоваться).

Класс и интерфейсные методы инициализации (§3.8), то есть, методы называют <clinit>, вызываются неявно виртуальной машиной Java; значение их access_flags элемент игнорируется.

Каждый интерфейсный метод неявно abstract, и, имеют - также ACC_ABSTRACT флаг устанавливается. Каждый интерфейсный метод неявно public (§2.13.5), и, имеют - также ACC_PUBLIC флаг устанавливается.

    name_index
Значение name_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Utf8_info (§4.4.7) структура, представляющая любые из специальных внутренних имен методов (§3.8), также <init> или <clinit>, или допустимое имя метода Java (§2.7), сохраненный как простое (не полностью определенный) имя (§2.7.1).

    descriptor_index
Значение descriptor_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Utf8_info (§4.4.7) структура, представляющая допустимый дескриптор метода Java (§4.3.3).

    attributes_count
Значение attributes_count элемент указывает на число дополнительных атрибутов (§4.7) этого метода.

    атрибуты []
Каждое значение attributes таблица должна быть структурой атрибута переменной длины. У метода может быть любое число дополнительных атрибутов (§4.7) связанный с этим.

Единственные атрибуты, определенные этой спецификацией для attributes таблица a method_info структура Code (§4.7.4) и Exceptions (§4.7.5) атрибуты.

Реализация виртуальной машины Java должна распознать Code (§4.7.4) и Exceptions (§4.7.5) атрибуты. Реализация виртуальной машины Java обязана тихо игнорировать любые другие атрибуты в attributes таблица a method_info структура, которую это не распознает. Атрибутам, не определенным в этой спецификации, не позволяют влиять на семантику class файл, но только предоставить дополнительную дескриптивную информацию (§4.7.1).


4.7 Атрибуты

Атрибуты используются в ClassFile (§4.1), field_info (§4.5), method_info (§4.6), и Code_attribute (§4.7.4) структуры class формат файла. У всех атрибутов есть следующий общий формат:


    attribute_info {
    	u2 attribute_name_index;
    	u4 attribute_length;
    	u1 info[attribute_length];
    }

Для всех атрибутов, attribute_name_index должен быть допустимый 16-разрядный индекс без знака в постоянный пул класса. constant_pool запись в attribute_name_index должен быть a CONSTANT_Utf8 (§4.4.7) строка, представляющая имя атрибута. Значение attribute_length элемент указывает на продолжительность последующей информации в байтах. Длина не включает начальные шесть байтов, которые содержат attribute_name_index и attribute_length элементы.

Определенные атрибуты предопределяются как часть class спецификация файла. Предопределенные атрибуты SourceFile (§4.7.2), ConstantValue (§4.7.3), Code (§4.7.4), Exceptions (§4.7.5), LineNumberTable (§4.7.6), и Local-VariableTable (§4.7.7) атрибуты. В пределах контекста их использования в этой спецификации, то есть, в attributes таблицы class резервируются файловые структуры, в которых они появляются, имена этих предопределенных атрибутов.

Из предопределенных атрибутов, Code, ConstantValue, и Exceptions атрибуты должны быть распознаны и правильно считаны a class средство чтения файлов для корректной интерпретации class файл виртуальной машиной Java. Использование остающихся предопределенных атрибутов является дополнительным; a class средство чтения файлов может использовать информацию, которую они содержат, и иначе должны тихо проигнорировать те атрибуты.

4.7.1 Определение и Именование Новых Атрибутов

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

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

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

Два атрибута, которые предназначаются, чтобы быть отличными, но которые, оказывается, используют то же самое название атрибута и являются той же самой длины, будут конфликтовать на реализациях, которые распознают любой атрибут. У атрибутов, определенных кроме Sun, должны быть имена, выбранные согласно соглашению о присвоении имен пакета, определенному Спецификацией языка Java. Например, у нового атрибута, определенного Netscape, могло бы быть имя "COM.Netscape.new-attribute".

Sun может определить дополнительные атрибуты в будущих версиях этого class спецификация файла.

4.7.2 Атрибут SourceFile

SourceFile атрибут является дополнительным атрибутом фиксированной длины в attributes таблица ClassFile (§4.1) структура. Может быть не больше, чем один SourceFile атрибут в attributes таблица данного ClassFile структура.

SourceFile у атрибута есть формат


    SourceFile_attribute {
    	u2 attribute_name_index;
    	u4 attribute_length;
    	u2 sourcefile_index;
    }

Элементы SourceFile_attribute структура следующие:

    attribute_name_index

Значение attribute_name_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Utf8_info (§4.4.7) структура, представляющая строку "SourceFile".

    attribute_length
Значение attribute_length элемент a SourceFile_attribute структура должна быть 2.

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

Только имя исходного файла дается SourceFile атрибут. Это никогда не представляет имя каталога, содержащего файл или абсолютный путь для файла. Например, SourceFile атрибут мог бы содержать имя файла foo.java но не путь UNIX /home/lindholm/foo.java.

4.7.3 Атрибут ConstantValue

ConstantValue атрибут является атрибутом фиксированной длины, используемым в attributes таблица field_info (§4.5) структуры. A ConstantValue атрибут представляет значение постоянного поля, которое должно быть (явно или неявно) static; то есть, ACC_STATIC бит (§Table 4.3) в flags элемент field_info структура должна быть установлена. Поле не обязано быть final. Может быть не больше, чем один ConstantValue атрибут в attributes таблица данного field_info структура. Постоянное поле, представленное field_info структура присваивается значение, на которое ссылается ConstantValue припишите как часть его инициализации (§2.16.4).

Каждая реализация виртуальной машины Java должна распознать ConstantValue атрибуты.

ConstantValue у атрибута есть формат


    ConstantValue_attribute {
    	u2 attribute_name_index;
    	u4 attribute_length;
    	u2 constantvalue_index;
    }

Элементы ConstantValue_attribute структура следующие:

    attribute_name_index

Значение attribute_name_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Utf8_info (§4.4.7) структура, представляющая строку "ConstantValue".

    attribute_length
Значение attribute_length элемент a ConstantValue_attribute структура должна быть 2.

    constantvalue_index
Значение constantvalue_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна дать постоянную величину, представленную этим атрибутом.

constant_pool запись должна иметь тип, соответствующий полю, как показано Таблицей 4.5.

Тип поля Тип записи
long CONSTANT_Long
float CONSTANT_Float
double CONSTANT_Double
int, short, char, byte, boolean CONSTANT_Integer
java.lang.String CONSTANT_String


4.7.4 Атрибут кода

Code атрибут является атрибутом переменной длины, используемым в attributes таблица method_info структуры. A Code атрибут содержит инструкции виртуальной машины Java и вспомогательную информацию для единственного метода Java, метод инициализации экземпляра (§3.8), или класс или интерфейсный метод инициализации (§3.8). Каждая реализация виртуальной машины Java должна распознать Code атрибуты. Должен быть точно один Code атрибут в каждом method_info структура.

Code у атрибута есть формат


    Code_attribute {
    	u2 attribute_name_index;
    	u4 attribute_length;
    	u2 max_stack;
    	u2 max_locals;
    	u4 code_length;
    	u1 code[code_length];
    	u2 exception_table_length;
    	{    	u2 start_pc;
    	      	u2 end_pc;
    	      	u2  handler_pc;
    	      	u2  catch_type;
    	}	exception_table[exception_table_length];
    	u2 attributes_count;
    	attribute_info attributes[attributes_count];
    }

Элементы Code_attribute структура следующие:

    attribute_name_index

Значение attribute_name_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Utf8_info (§4.4.7) структура, представляющая строку "Code".

    attribute_length
Значение attribute_length элемент указывает на длину атрибута, исключая начальные шесть байтов.

    max_stack
Значение max_stack элемент дает максимальное количество слов на стеке операнда в любой точке во время выполнения этого метода.

    max_locals
Значение max_locals элемент дает число локальных переменных, используемых этим методом, включая параметры, которые передают к методу вызову. Индекс первой локальной переменной 0. Самый большой индекс локальной переменной для значения с одним словом max_locals-1. Самый большой индекс локальной переменной для значения с двумя словами max_locals-2.

    code_length
Значение code_length элемент подает число байтов code массив для этого метода. Значение code_length должно быть больше чем нуль; code массив не должен быть пустым.

    код []
code массив дает фактические байты кода виртуальной машины Java, которые реализуют метод.

Когда code массив читается в память на байте адресуемая машина, если первый байт массива будет выровненный на 4-байтовой границе, то tableswitch и lookupswitch 32-разрядные смещения составят выровненные 4 байта; сошлитесь на описания тех инструкций для получения дополнительной информации о последствиях code выравнивание массива.

Подробные ограничения на содержание code массив обширен и дается в отдельном участке (§4.8).

    exception_table_length
Значение exception_table_length элемент подает число записей exception_table таблица.

    exception_table []
Каждая запись в exception_table массив описывает один обработчик исключений в code массив. Каждый exception_table запись содержит следующие элементы:

    start_pc, end_pc
Значения этих двух элементов start_pc и end_pc укажите на диапазоны в code массив, в котором обработчик исключений является активным. Значение start_pc должен быть допустимый индекс в code массив кода операции инструкции. Значение end_pc любой должен быть допустимым индексом в code массив кода операции инструкции, или должно быть равным code_length, длина code массив. Значение start_pc должны быть меньше чем значение end_pc.

start_pc является содержащим и end_pc является монопольным; то есть, обработчик исключений должен быть активным, в то время как счетчик программы в пределах интервала [start_pc, end_pc).2

    handler_pc
Значение handler_pc элемент указывает на запуск обработчика исключений. Значение элемента должно быть допустимым индексом в code выстройте, должен быть индекс кода операции инструкции, и должны быть меньше чем значение code_length элемент.

    catch_type
Если значение catch_type элемент является ненулевым, это должен быть допустимый индекс в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Class_info структура (§4.4.1), представляющая класс исключений, что этот обработчик исключений определяется, чтобы поймать. Этот класс должен быть классом Throwable или один из его подклассов. Обработчик исключений вызовут, только если выданное исключение является экземпляром данного класса или одним из его подклассов.

Если значение catch_type элемент является нулем, этот обработчик исключений вызывают для всех исключений. Это используется, чтобы реализовать finally (см. Раздел 7.13, "Компилируя наконец").

    attributes_count
Значение attributes_count элемент указывает на число атрибутов Code атрибут.

    атрибуты []
Каждое значение attributes таблица должна быть структурой атрибута переменной длины. A Code у атрибута может быть любое число дополнительных атрибутов, связанных с этим.

В настоящий момент, LineNumberTable (§4.7.6) и LocalVariableTable (§4.7.7) атрибуты, оба из которых содержат отладочную информацию, определяются и используются с Code атрибут.

Реализации виртуальной машины Java разрешают тихо проигнорировать любые атрибуты в attributes таблица a Code атрибут. Атрибутам, не определенным в этой спецификации, не позволяют влиять на семантику class файл, но только предоставить дополнительную дескриптивную информацию (§4.7.1).

4.7.5 Атрибут исключений

Exceptions атрибут является атрибутом переменной длины, используемым в attributes таблица a method_info (§4.6) структура. Exceptions атрибут указывает, который проверял исключения, которые может выдать метод. Должен быть точно один Exceptions атрибут в каждом method_info структура.

Exceptions у атрибута есть формат


    Exceptions_attribute {
    	u2 attribute_name_index;
    	u4 attribute_length;
    	u2 number_of_exceptions;
    	u2 exception_index_table[number_of_exceptions];
    }

Элементы Exceptions_attribute структура следующие:

    attribute_name_index

Значение attribute_name_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть CONSTANT_Utf8_info (§4.4.7) структура, представляющая строку "Exceptions".

    attribute_length
Значение attribute_length элемент указывает на длину атрибута, исключая начальные шесть байтов.

    number_of_exceptions
Значение number_of_exceptions элемент указывает на число записей в exception_index_table.

    exception_index_table []
Каждое ненулевое значение в exception_index_table массив должен быть допустимым индексом в constant_pool таблица. Для каждого табличного элемента, если exception_index_table[я] != 0, где 0I £ < number_of_exceptions, тогда constant_pool запись по индексу exception_index_table[я] должен быть a CONSTANT_Class_info структура (§4.4.1), представляющая тип класса, который этот метод, как объявляют, бросает.

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

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

4.7.6 Атрибут LineNumberTable

LineNumberTable атрибут является дополнительным атрибутом переменной длины в attributes таблица a Code (§4.7.4) атрибут. Это может использоваться отладчиками, чтобы определить который часть виртуальной машины Java code массив соответствует данному номеру строки в исходном исходном файле Java. Если LineNumberTable атрибуты присутствуют в attributes таблица данного Code атрибут, тогда они могут появиться в любом порядке. Кроме того, многократный LineNumberTable атрибуты могут вместе представить данную строку исходного файла Java; то есть, LineNumberTable атрибуты не должны быть непосредственными с исходными строками 3

LineNumberTable у атрибута есть формат


    LineNumberTable_attribute {
    	u2 attribute_name_index;
    	u4 attribute_length;
    	u2 line_number_table_length;
    	{  u2 start_pc;	     
    	   u2 line_number;	     
    	} line_number_table[line_number_table_length];
    }

Элементы LineNumberTable_attribute структура следующие:

    attribute_name_index

Значение attribute_name_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Utf8_info (§4.4.7) структура, представляющая строку "LineNumberTable".

    attribute_length
Значение attribute_length элемент указывает на длину атрибута, исключая начальные шесть байтов.

    line_number_table_length
Значение line_number_table_length элемент указывает на число записей в line_number_table массив.

    line_number_table []
Каждая запись в line_number_table массив указывает, что номер строки в исходном исходном файле Java изменяется в поданной точке code массив. Каждая запись должна содержать следующие элементы:

    start_pc
Значение start_pc элемент должен указать на индекс в code массив, в котором начинается код для новой строки в исходном исходном файле Java. Значение start_pc должны быть меньше чем значение code_length элемент Code атрибут которого это LineNumberTable атрибут.

    line_number
Значение line_number элемент должен дать соответствующий номер строки в исходном исходном файле Java.

4.7.7 Атрибут LocalVariableTable

LocalVariableTable атрибут является дополнительным атрибутом переменной длины a Code (§4.7.4) атрибут. Это может использоваться отладчиками, чтобы определить значение данной локальной переменной во время выполнения метода. Если LocalVariableTable атрибуты присутствуют в attributes таблица данного Code атрибут, тогда они могут появиться в любом порядке. Может быть не больше, чем один LocalVariableTable атрибут на локальную переменную в Code атрибут.

LocalVariableTable у атрибута есть формат


    LocalVariableTable_attribute {
    	u2 attribute_name_index;
    	u4 attribute_length;
    	u2 local_variable_table_length;
    	{  u2 start_pc;
    	    u2 length;
    	    u2 name_index;
    	    u2 descriptor_index;
    	    u2 index;
    	} local_variable_table[
    			local_variable_table_length];
    }	

Элементы LocalVariableTable_attribute структура следующие:

    attribute_name_index

Значение attribute_name_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна быть a CONSTANT_Utf8_info (§4.4.7) структура, представляющая строку "LocalVariableTable".

    attribute_length
Значение attribute_length элемент указывает на длину атрибута, исключая начальные шесть байтов.

    local_variable_table_length
Значение local_variable_table_length элемент указывает на число записей в local_variable_table массив.

    local_variable_table []
Каждая запись в local_variable_table массив указывает на диапазон code выстройте смещения, в пределах которых у локальной переменной есть значение. Это также указывает на индекс в локальные переменные текущего фрейма, в котором может быть найдена та локальная переменная. Каждая запись должна содержать следующие элементы:

    start_pc, длина
У данной локальной переменной должно быть значение в индексах в code массив в интервале [start_pc, start_pc+length], то есть, между start_pc и start_pc+length включительно. Значение start_pc должен быть допустимый индекс в code массив этого Code атрибут кода операции инструкции. Значение start_pc+length должен быть любой допустимый индекс в code массив этого Code атрибут кода операции инструкции, или первый индекс вне конца этого code массив.

    name_index, descriptor_index
Значение name_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна содержать a CONSTANT_Utf8_info (§4.4.7) структура, представляющая допустимое имя локальной переменной Java, сохраненное как простое имя (§2.7.1).

Значение descriptor_index элемент должен быть допустимым индексом в constant_pool таблица. constant_pool запись по тому индексу должна содержать a CONSTANT_Utf8_info (§4.4.7) структура, представляющая допустимый дескриптор для локальной переменной Java. У дескрипторов локальной переменной Java есть та же самая форма как полевые дескрипторы (§4.3.2).

    индекс
Данная локальная переменная должна быть в index в локальных переменных его метода. Если локальная переменная в index тип с двумя словами (double или long), это занимает обоих index и index+1.


4.8 Ограничения на Код виртуальной машины Java

Код виртуальной машины Java для метода, метод инициализации экземпляра (§3.8), или класс или интерфейсный метод инициализации (§3.8) сохранен в code массив Code атрибут a method_info структура a class файл. Этот раздел описывает ограничения, связанные с содержанием Code_attribute структура.

4.8.1 Статические Ограничения

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

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

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

4.8.2 Структурные ограничения

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


4.9 Проверка Файлов класса

Даже при том, что компилятор Java Sun пытается произвести только файлы класса, которые удовлетворяют все статические ограничения в предыдущих разделах, у виртуальной машины Java нет никакой гарантии, что любой файл, который просят загрузить, был сгенерирован тем компилятором, или должным образом формируется. Приложения, такие как браузер всемирной паутины HotJava Sun не загружают исходный код, который они тогда компилируют; эти приложения уже загружают - скомпилированный class файлы. Браузер HotJava должен определить ли class файл был произведен защищенным компилятором Java или противником, пытающимся использовать интерпретатор.

Дополнительной проблемой со временем компиляции, проверяя является скос версии. Пользователь, возможно, успешно скомпилировал класс, сказать PurchaseStockOptions, быть подклассом TradingClass. Но определение TradingClass возможно, изменился в пути, который не является совместимым с существующими ранее двоичными файлами со времени, класс был скомпилирован. Методы, возможно, были удалены, или имели свои типы возврата или измененные модификаторы. Поля, возможно, изменили типы или изменились от переменных экземпляра до переменных класса. Модификаторы доступа метода или переменной, возможно, изменились от public к private. Для обсуждения этих проблем см. Главу 13, "Совместимость на уровне двоичных кодов," в Спецификации языка Java.

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

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

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

Sun class верификатор файла независим от любого компилятора Java. Это должно сертифицировать весь код, сгенерированный текущим компилятором Java Sun; это должно также сертифицировать код, который другие компиляторы могут генерировать, так же как код, который не мог возможно генерировать текущий компилятор. Любой class файл, который удовлетворяет структурные критерии и статические ограничения, будет сертифицирован верификатором.

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

4.9.1 Процесс Проверки

class верификатор файла работает в четырех передачах:

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

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

Передача 2: Когда class файл соединяется, верификатор выполняет всю дополнительную проверку, которая может быть сделана, не смотря на code массив Code атрибут (§4.7.4). Проверки, выполняемые этой передачей, включают следующее:

Отметьте, что, когда это смотрит на поле и ссылки метода, эта передача не проверяет, чтобы удостовериться, что данное поле или метод фактически существуют в данном классе; и при этом это не проверяет, что данные дескрипторы типа обращаются к реальным классам. Это только проверяет, что эти элементы хорошо формируются. Более подробная проверка задерживается до передач 3 и 4.

Передача 3: Все еще во время соединения, верификатор проверяет code массив Code атрибут для каждого метода class файл, выполняя анализ потока данных каждого метода. Верификатор гарантирует, что в любой данной точке в программе, независимо от того какой путь выполнения кода берется, чтобы достигнуть той точки:

Для дополнительной информации об этой передаче см. Раздел 4.9.2, "Верификатор Байт-кода."

Передача 4: По причинам эффективности задерживаются определенные тесты, которые могли в принципе быть выполнены в Передаче 3, до первого раза фактически вызывается код для метода. Таким образом, Передача 3 из верификатора избегает загружаться class файлы, если это не имеет к.

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

Передача 4 является виртуальной передачей, проверка которой делается соответствующими инструкциями виртуальной машины Java. В первый раз инструкция, что ссылается на тип, выполняется, выполняющаяся инструкция делает следующее:

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

Виртуальная машина Java не должна проверить тип объекта на стеке операнда. Та проверка была уже сделана Передачей 3. Ошибки, которые обнаруживаются в Передаче 4 экземпляра причины подклассов LinkageError быть брошенным.

Виртуальной машине Java позволяют выполнить любую из Передачи 4 шага, за исключением класса или интерфейсной инициализации, как часть Передачи 3; см. 2.16.1, "Запуск Виртуальной машины" для примера и большего количества обсуждения.

В реализации виртуальной машины Java Sun, после того, как была выполнена проверка, инструкция в коде виртуальной машины Java заменяется альтернативной формой инструкции (см. Главу 9, "Оптимизация"). Например, код операции new заменяется new_quick. Эта альтернативная инструкция указывает, что проверка, необходимая этой инструкции, имела место и не должна быть выполнена снова. Последующие вызовы метода таким образом будут быстрее. Это недопустимо для этих альтернативных форм инструкции, чтобы появиться в class файлы, и с ними никогда не должен встречаться верификатор.

4.9.2 Верификатор Байт-кода

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

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

Для каждой инструкции метода верификатор записывает содержание стека операнда и содержание локальных переменных до выполнения той инструкции. Для стека операнда это должно знать высоту стека и тип каждого значения на этом. Для каждой локальной переменной это должно знать или тип содержания той локальной переменной, или что локальная переменная содержит неприменимое или неизвестное значение (это могло бы быть неинициализированным). Верификатор байт-кода не должен различить целочисленные типы (например, byte, short, char) когда определение значения вводит на стеке операнда.

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

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

  1. Выберите инструкцию виртуальной машины, "измененный" бит которой устанавливается. Если никакая инструкция не остается, чей "измененный" бит устанавливается, метод был успешно проверен. Иначе, выключите "измененный" бит выбранной инструкции.
  2. Смоделируйте эффект инструкции по стеку операнда и локальным переменным:
  3. Определите инструкции, которые могут следовать за текущей командой. Инструкции преемника могут быть одним из следующего:
  4. Объедините состояние стека операнда и локальных переменных в конце выполнения текущей команды в каждую из инструкций преемника. В особом случае передачи управления в обработчик исключений стек операнда устанавливается содержать единственный объект типа исключения, обозначенного информацией об обработчике исключений.
  5. Продолжайте в шаге 1.
Чтобы объединить два стека операнда, число значений на каждом стеке должно быть идентичным. Типы значений на стеках должны также быть идентичными, за исключением того, что по-другому введенный reference значения могут появиться в соответствующих местах на двух стеках. В этом случае объединенный стек операнда содержит a reference к экземпляру первого общего суперкласса или общего суперинтерфейса двух типов. Такой ссылочный тип всегда существует потому что тип Object супертип всего класса и интерфейсных типов. Если стеки операнда не могут быть объединены, проверка сбоев метода.

Чтобы объединить два состояния локальной переменной, соответствующие пары локальных переменных сравниваются. Если два типа не идентичны, то, если оба не содержат reference значения, записи верификатора, что локальная переменная содержит неприменимое значение. Если обе из пары локальных переменных содержат reference значения, объединенное состояние содержит a reference к экземпляру первого общего суперкласса двух типов.

Если поток данных, анализатор работает на методе, не сообщая об отказе проверки, то метод был успешно проверен Передачей 3 из class верификатор файла.

Определенные инструкции и типы данных усложняют поток данных анализатор. Мы теперь исследуем каждый из них более подробно.

4.9.3 Длинные целые и Удваиваются

Значения long и double типы каждый берет два последовательных слова на стеке операнда и в локальных переменных.

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

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

Контакт с 64-разрядными количествами на стеке операнда более прост; верификатор обрабатывает их как единые блоки на стеке. Например, код проверки для dadd кода операции (добавляют два double значения), проверяет, что лучшие два элемента на стеке имеют оба тип double. Когда вычисление операнда складывает длину, значения типа long и double имейте длину два.

Невведенные инструкции, которые управляют стеком операнда, должны обработать значения типа double и long как атомарный. Например, верификатор сообщает об отказе, если главное значение на стеке является a double и это встречается с инструкцией те, которые выталкивают или копируют. Инструкции pop2 или dup2 должны использоваться вместо этого.

4.9.4 Методы Инициализации экземпляра и Недавно Создаваемые Объекты

Создание нового экземпляра класса является многошаговым процессом. Оператор Java


    ...
    new myClass(i, j, k);
    ...

может быть реализован следующим:


    ...
    new 	#1		// Allocate uninitialized space for myClass
    dup			// Duplicate object on the operand stack
    iload_1			// Push i
    iload_2			// Push j
    iload_3			// Push k
    invokespecial myClass.<init>	         // Initialize object
    ...

Эта последовательность инструкции листы недавно создаваемый и инициализированный объект сверху стека операнда. (Больше примеров компиляции кода Java к набору команд виртуальной машины Java дается в Главе 7, "Компилирующей для виртуальной машины Java.")

Метод инициализации экземпляра <init> для класса myClass рассматривает новый неинициализированный объект как this параметр в локальной переменной 0. Это должно или вызвать альтернативный метод инициализации экземпляра для класса myClass или вызовите метод инициализации суперкласса на this объект прежде, чем будет позволено сделать что-либо еще с this.

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

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

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

new InputStream(new Foo(), new InputStream("foo"))

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

У допустимой последовательности инструкции не должно быть неинициализированного объекта на стеке операнда или в локальной переменной во время назад ответвление, или в локальной переменной в коде, защищенном обработчиком исключений или a finally пункт. Иначе, окольная часть кода могла бы дурачить верификатор, заставляя думать, это инициализировало экземпляр класса, когда это, фактически, инициализировало экземпляр класса, создаваемый в предыдущей передаче через цикл.

4.9.5 Обработчики исключений

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

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

4.9.6 Исключения и finally

Учитывая фрагмент кода Java


    ...
    try {
    startFaucet();
    waterLawn();
    } finally {
    stopFaucet();
    }
    ...

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

Реализовывать try-finally создайте, компилятор Java использует средства обработки исключений вместе с двумя специальными инструкциями jsr ("переход к подпрограмме"), и мочите ("возврат из подпрограммы"). finally пункт компилируется как подпрограмма в пределах кода виртуальной машины Java для его метода, очень как код для обработчика исключений. Когда jsr инструкция, которая вызывает подпрограмму, выполняется, это продвигает свой обратный адрес, адрес инструкции после jsr, который выполняется на стек операнда как значение типа returnAddress. Код для подпрограммы хранит обратный адрес в локальной переменной. В конце подпрограммы мочить инструкция выбирает обратный адрес от локальной переменной и передает управление инструкции в обратном адресе.

Управление может быть передано finally пункт ( finally подпрограмма может быть вызвана) несколькими различными способами. Если try пункт обычно завершается, finally подпрограмма вызывается через jsr инструкцию прежде, чем оценить следующее выражение Java. A break или continue в try пункт, который передает управление вне try пункт выполняет jsr к коду для finally пункт сначала. Если try пункт выполняет a return, скомпилированный код делает следующее:

  1. Сохраняет возвращаемое значение (если любой) в локальной переменной.
  2. Выполняет jsr к коду для finally пункт.
  3. По возврату из finally пункт, возвращает значение, сохраненное в локальной переменной.
Компилятор устанавливает специальный обработчик исключений, который ловит любое исключение, выданное try пункт. Если исключение добавляется try пункт, этот обработчик исключений делает следующее:

  1. Сохраняет исключение в локальной переменной.
  2. Выполняет jsr к finally пункт.
  3. По возврату из finally пункт, повторно бросает исключение.
Для получения дополнительной информации о реализации Java try-finally создайте, см. Раздел 7.13, "Компилируя наконец."

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

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

Проверка кода, который содержит a finally пункт усложняется. Основная идея является следующим:


4.10 Ограничения виртуальной машины Java и class Формат файла

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


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

2 факт это end_pc является монопольным, историческая ошибка в виртуальной машине Java: если код виртуальной машины Java для метода точно 65535 байтов длиной и заканчивается инструкцией, которая один байт длиной, то та инструкция не может быть защищена обработчиком исключений. Разработчик компилятора может работать вокруг этой ошибки, ограничивая максимальный размер сгенерированного кода виртуальной машины Java для любого метода, метода инициализации экземпляра, или статического инициализатора (размер любого code массив) к 65534 байтам.

3 javac компилятор в JDK Sun 1.0.2 выпуска может фактически генерировать LineNumberTable атрибуты, которые не находятся в порядке номера строки и которые не являются непосредственными с исходными строками. Это неудачно, поскольку мы предпочли бы определять непосредственное, упорядоченное отображение LineNumberTable атрибуты, чтобы определить источник строк, но должен уступить обратной совместимости.


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

Спецификация Виртуальной машины Java

Авторское право © 1996, 1997 Sun Microsystems, Inc. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления к jvm@java.sun.com

free hit counter