структура файла класса
Содержимое, хранящееся в файле Class, называется ByteCode и включает в себя набор инструкций JVM и таблицу символов, а также некоторую другую вспомогательную информацию.
Файл класса представляет собой набор бинарных потоков на основе 8-битных байтов.Каждый элемент данных расположен в файле класса строго по порядку и компактно, без добавления какого-либо разделителя посередине.Практически все содержимое, хранящееся во всем файле класса, программа запущена, необходимые данные, пропусков нет.
При обнаружении элемента данных с пространством более 8 байтов он будет разделен на несколько 8-битных байтов для хранения в соответствии с первым старшим порядком.
В файле Class есть два типа данных: числа без знака и таблицы.
беззнаковое число
Числа без знака относятся к базовым типам данных, где u1, u2, u4, u8 представляют числа без знака в один байт, два байта...; числа без знака используются для описания чисел, индексных ссылок, количественных значений или UTF-8. закодированное строковое значение.
поверхность
Таблица — это составной тип данных, состоящий из нескольких чисел без знака или других таблиц в качестве элементов данных, обычно оканчивающихся на «_info», который используется для описания структуры данных файла класса.
Особенности: Экономьте место для хранения и повышайте производительность обработки
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];
}
- магическое число
- Версия файла класса
- постоянный пул
- знак доступа
- Индекс класса, индекс родительского класса, коллекция индексов интерфейса
- Коллекция полевых таблиц
- Коллекция таблиц методов
- коллекция листов свойств
u2 означает беззнаковые 2 байта u4 означает беззнаковые 4 байта
Концепция и значение дизайна файла класса
1. Магия магических чисел
Единственная функция магического числа — определить, является ли файл файлом класса, который может быть принят виртуальной машиной. Магическое значение зафиксировано на 0xCAFEBABE и не изменится.
Докажите магический эффект
Создайте файл класса magic.class , содержимое которого является магическим тестом, запустите напрямуюjava magic
работать:
84407@FantJ MINGW64 ~/Desktop
$ java magictest
▒▒▒▒: ▒▒▒▒▒▒▒▒ magictest ʱ▒▒▒▒ LinkageError
java.lang.ClassFormatError: Incompatible magic value 1886741100 in class file magictest
Смысл ошибки таков: магия противоречит, и тогда дается десятичное число магического значения, то какое должно быть распознанное магическое десятичное число.
должно быть3405691582
Что ж, тогда я использую обычный файл Java, скомпилированный javac, для создания файла класса и просмотра его с помощью средства просмотра двоичных файлов:
младшая_версия, основная_версия
Четыре цифры после магического числа: представляют версию байт-кода, которые соответственно представляют вторичную и основную версии файла класса. Наиболее распространенные сегодня версии: jdk1.8:52 jdk1.7:51 jdk1.6:50
Соответствующий номер версии — 52, то есть jdk1.8.Версия обратно совместима
2. constant_pool_count
Счетчик пула констант, значение равно количеству членов в таблице Constant_pool плюс 1, занимает два байта
3. Constant_pool[] постоянный пул
Инструкции виртуальной машины Java при выполнении полагаются на информацию о символах в таблице пула констант (constant_pool).
Все записи пула констант имеют следующий общий формат:
cp_info {
u1 tag;
u1 info[];
}
Тег содержимого элемента info[] определяется типом. Допустимые типы и соответствующие значения тегов перечислены в следующей таблице.
постоянный тип | ценность |
---|---|
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 |
CONSTANT_MethodHandle | 15 |
CONSTANT_MethodType | 16 |
CONSTANT_InvokeDynamic | 18 |
3.1 Структура CONSTANT_Class_info
Представляет класс или интерфейс
CONSTANT_Class_info {
u1 tag;
u2 name_index;
}
name_index
Должен быть действительным индексом в постоянном пуле
3.2 Структуры CONSTANT_Fieldref_info, CONSTANT_Methodref_info и CONSTANT_InterfaceMethodref_info
Поле:
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;
}
class_index
Должен быть допустимым индексом для пула констант. Запись пула констант в этом индексе должна быть структурой CONSTANT_Class_info, представляющей класс или интерфейс, а текущее поле или метод является членом этого класса или интерфейса.
CONSTANT_Methodref_info
структурныйclass_index
Тип элемента должен быть классом (не интерфейсом).CONSTANT_InterfaceMethodref_info
структурныйclass_index
Тип элемента должен быть интерфейсом (не классом).CONSTANT_Fieldref_info
структурныйclass_index
Тип элемента может быть либо классом, либо интерфейсом.
name_and_type_index
Должен быть допустимым индексом в пуле констант, представляющим имя и дескриптор текущего поля или метода.
вCONSTANT_Fieldref_info
структура, данный дескриптор должен быть字段
Дескриптор. иCONSTANT_Methodref_info
иCONSTANT_InterfaceMethodref_info
Указанный дескриптор должен быть方法
Дескриптор.
3.3 Структура CONSTANT_String_info
Структура, используемая для представления строки
CONSTANT_String_info {
u1 tag;
u2 string_index;
}
string_index
Должен быть допустимым индексом в пуле констант, в котором запись пула констант должна быть CONSTANT_Utf8_info
Структура, представляющая набор последовательностей кодовых точек Unicode, которые в конечном итоге будут инициализированы как объект String.
3.4 Структуры CONSTANT_Integer_info и CONSTANT_Float_info
Числовые константы, представляющие 4 байта (int и float):
CONSTANT_Integer_info {
u1 tag;
u4 bytes;
}
CONSTANT_Float_info {
u1 tag;
u4 bytes;
}
3.5 Структуры CONSTANT_Long_info и CONSTANT_Double_info
Числовая константа, представляющая 8 байтов (long и double)
CONSTANT_Long_info {
u1 tag;
u4 high_bytes;
u4 low_bytes;
}
CONSTANT_Double_info {
u1 tag;
u4 high_bytes;
u4 low_bytes;
}
3.6 Структура CONSTANT_NameAndType_info
Представляет поле или метод, но в отличие от трех структур, описанных выше, структура CONSTANT_NameAndType_info не идентифицирует класс или интерфейс, к которому она принадлежит.
CONSTANT_NameAndType_info {
u1 tag;
u2 name_index;
u2 descriptor_index;
}
name_index
Значение записи должно быть допустимым индексом в пуле констант, а запись пула констант в этом индексе должна быть структурой CONSTANT_Utf8_info, которая либо представляет имя специального метода, либо допустимое поле или метод. Неполное имя (Unqualified Name) .
descriptor_index
Значение записи должно быть допустимым индексом в пуле констант, а запись пула констант в этом индексе должна быть структурой CONSTANT_Utf8_info, представляющей допустимое поле или дескриптор метода.
3.7 Структура CONSTANT_Utf8_info
значение, используемое для представления строковых констант
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
}
Содержимое структуры CONSTANT_Utf8_info:length
атрибут определяет длину
3.8 Структура CONSTANT_MethodHandle_info
Представляет дескриптор метода
CONSTANT_MethodHandle_info {
u1 tag;
u1 reference_kind;
u2 reference_index;
}
reference_kind
Значение элемента, которое должно быть от 1 до 9 включительно, определяет тип дескриптора метода.
- если
reference_kind
стоимость товара1(REF_getField)、2(REF_getStatic)、3(REF_putField)或4(REF_putStatic)
, то запись пула констант в индексе reference_index должна быть структурой CONSTANT_Fieldref_info, представляющей дескриптор метода, созданный полем. - если
reference_kind
Стоимость предмета5(REF_invokeVirtual)、6(REF_invokeStatic)、7(REF_invokeSpecial)或8(REF_newInvokeSpecial)
, то постоянный пул находится вreference_index
элемент в индексе должен бытьCONSTANT_Methodref_info
Структура, представляющая дескриптор метода, созданный методом или конструктором класса. - если
reference_kind
Стоимость предмета9(REF_invokeInterface)
, то запись пула констант в индексе reference_index должна быть структурой CONSTANT_InterfaceMethodref_info, представляющей дескриптор метода, созданный методом интерфейса. - если
reference_kind
Стоимость предмета5(REF_invokeVirtual)、6(REF_invokeStatic)、7(REF_invokeSpecial)或9(REF_invokeInterface)
, то метод, соответствующий дескриптору метода, не может быть методом инициализации() экземпляра или методом инициализации класса(). - если
reference_kind
Стоимость предмета8(REF_newInvokeSpecial)
, то метод, соответствующий дескриптору метода, должен быть методом инициализации() экземпляра.
3.9 Структура CONSTANT_MethodType_info
Тип метода представления
CONSTANT_MethodType_info {
u1 tag;
u2 descriptor_index;
}
3.10 Структура CONSTANT_InvokeDynamic_info
Указывает метод начальной загрузки, используемый инструкцией invokedynamic, имя динамического вызова, используемое методом начальной загрузки, параметры и тип возврата запроса, а также, возможно, дополнительные константы, называемые последовательностью статических аргументов.
CONSTANT_InvokeDynamic_info {
u1 tag;
u2 bootstrap_method_attr_index;
u2 name_and_type_index;
}
bootstrap_method_attr_index
Значение элемента должно быть ссылкой на таблицу методов загрузки в текущем файле класса.bootstrap_methods[]
Допустимый индекс в массиве.
name_and_type_index
Значение записи должно быть действительным индексом в текущем пуле констант, в котором запись пула констант должна бытьCONSTANT_NameAndType_info
Структура, представляющая имя метода и дескриптор метода.
4. access_flags: флаги доступа
Флаги доступа, access_flags — это флаг маски, используемый для указания прав доступа и основных атрибутов класса или интерфейса. Диапазон значений и соответствующее значение флагов доступа показаны в следующей таблице.
название тэга | ценность | значение |
---|---|---|
ACC_PUBLIC | 0x0001 | Доступ к ним может осуществляться вне класса пакета. |
ACC_FINAL | 0x0010 | Подклассы не допускаются. |
ACC_SUPER | 0x0020 | Методы родительского класса, требующие специальной обработки при использовании invokespecial. |
ACC_INTERFACE | 0x0200 | Идентификаторы определяют интерфейсы, а не классы. |
ACC_ABSTRACT | 0x0400 | не может быть создан. |
ACC_SYNTHETIC | 0x1000 | Идентифицирует код, который не создан из исходного кода Java. |
ACC_ANNOTATION | 0x2000 | Определяет тип аннотации |
ACC_ENUM | 0x4000 | Определяет типы перечисления |
5. this_class: индекс класса
Значение this_class должно быть допустимым значением индекса для элемента в таблице Constant_pool.
— допустимое значение индекса для элемента в таблице Constant_pool, указывающее количество позиций, указывающих на пул констант.
6. super_class: индекс родительского класса
Указывает прямой родительский класс класса, определенного в файле классов. Если значение super_class в файле классов равно 0, то файл классов может определять только класс java.lang.Object, и это единственный класс без родительского сорт.
является допустимым значением индекса для элемента в таблице Constant_pool, указывающим количество позиций, указывающих на постоянный пул.
7. interfaces_count: счетчик интерфейсов
Указывает, что этот класс имеет несколько интерфейсов.
8. interfaces[]: таблица интерфейсов
Порядок интерфейсов, представленных элементами, такой же, как порядок интерфейсов, указанный в соответствующем исходном коде (слева направо), то есть interfaces[0] соответствует самому левому интерфейсу в исходном коде.
является допустимым значением индекса для элемента в таблице Constant_pool, указывающим количество позиций, указывающих на постоянный пул.
Указывает количество прямых родительских интерфейсов текущего класса или интерфейса
9. fields_count: счетчик полей
Указывает количество элементов массива fields[] текущего файла класса.
10. fields[]: таблица полей
Каждый член должен быть элементом данных структуры fields_info, описывающей все поля, объявленные текущим классом или интерфейсом, за исключением унаследованных от родительского класса или родительского интерфейса.
Используется для представления полного описания поля в текущем классе или интерфейсе.
field_info {
u2 access_flags;
u2 name_index; //对常量池的一个有效索引
u2 descriptor_index; //对常量池的一个有效索引
u2 attributes_count; //当前字段的附加属性的数量
attribute_info attributes[attributes_count];
}
access_flags
Значение элемента — это флаг маски, определяющий права доступа и базовые свойства поля. Диапазон значений и соответствующее значение access_flags показаны в следующей таблице:
название тэга | ценность | инструкция |
---|---|---|
ACC_PUBLIC | 0x0001 | public, указывающий, что к полю можно получить доступ из любого пакета. |
ACC_PRIVATE | 0x0002 | private, указывающее, что поле может быть вызвано только самим классом. |
ACC_PROTECTED | 0x0004 | защищенный, указывающий, что поле может быть вызвано подклассами. |
ACC_STATIC | 0x0008 | static, указывающий на статическое поле. |
ACC_FINAL | 0x0010 | final, указывающий, что значение не может быть изменено после определения поля. |
ACC_VOLATILE | 0x0040 | volatile, указывая на то, что поле является изменчивым. |
ACC_TRANSIENT | 0x0080 | переходный, указывающий, что поле не будет сериализовано. |
ACC_SYNTHETIC | 0x1000 | Поле представления автоматически генерируется компилятором. |
ACC_ENUM | 0x4000 | enum, указывающий, что поле является типом перечисления. |
attributes
Значение каждого члена таблицы должно бытьattribute结构
, поле может иметь любое количество связанных свойств.
11. method_count: счетчик методов
Значение method_count представляет количество членов массива методов [] текущего файла класса, и каждый элемент в массиве методов [] является элементом данных структуры method_info.
12. method[]: таблица методов
Структура method_info может представлять все методы, определенные в классах и интерфейсах, включая методы экземпляра, методы класса, методы инициализации экземпляра и методы инициализации класса или интерфейса. Массив методов [] описывает только методы, объявленные в текущем классе или интерфейсе, за исключением методов, унаследованных от родительского класса или родительского интерфейса.
Каждый член массива методов [] должен быть элементом данных структуры method_info, представляющей полное описание метода в текущем классе или интерфейсе.
method_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
access_flags
Значением элемента является флаг маски, используемый для определения прав доступа и основных атрибутов текущего метода.Диапазон значений и соответствующее значение access_flags показаны в следующей таблице.
название тэга | ценность | инструкция |
---|---|---|
ACC_PUBLIC | 0x0001 | общедоступный, доступ к методу возможен из-за пределов пакета |
ACC_PRIVATE | 0x0002 | private, доступ к методу возможен только в этом классе |
ACC_PROTECTED | 0x0004 | защищенный, метод может быть доступен сам по себе и подклассам |
ACC_STATIC | 0x0008 | статический, статический метод |
ACC_FINAL | 0x0010 | final, метод не может быть переопределен (переопределен) |
ACC_SYNCHRONIZED | 0x0020 | синхронизированный, метод синхронизируется монитором |
ACC_BRIDGE | 0x0040 | мост, метод генерируется компилятором |
ACC_VARARGS | 0x0080 | Представляет метод с параметром переменной длины. |
ACC_NATIVE | 0x0100 | native, метод ссылается на собственный метод на языке, отличном от Java. |
ACC_ABSTRACT | 0x0400 | абстрактный, метод не имеет конкретной реализации |
ACC_STRICT | 0x0800 | strictfp, метод использует FP-строгий формат с плавающей запятой. |
ACC_SYNTHETIC | 0x1000 | Метод отсутствует в исходном файле, он генерируется компилятором. |
name_index
иdescriptor_index
Два свойства являются действительным индексом в пуле констант.attributes_count
Значение элемента представляет количество дополнительных свойств для этого метода.attributes
Значение каждого члена таблицы должно бытьattribute
Структура, метод может иметь любое количество связанных с ним свойств.
13. attribute_count: счетчик атрибутов
Каждый элемент в таблице атрибутов является элементом данных структуры attribute_info.
Значение attribute_count указывает количество элементов в таблице атрибутов текущего файла класса.
14. attribute[]: таблица атрибутов
Значение каждого элемента в таблице атрибутов должно быть структурой attribute_info.В формате файла Class используются структура ClassFile, структура field_info, структура method_info и структура Code_attribute.Общий формат всех атрибутов следующий:
attribute_info {
u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length];
}
attribute_name_index
Должен быть допустимым 16-битным беззнаковым индексом в константном пуле текущего файла класса. Представляет имя текущего свойства.
attribute_length
Значение элемента дает длину следующих байтов, не включаяattribute_name_index
иattribute_name_index
6 байт для элемента.
14.1 Свойство ConstantValue
Атрибут ConstantValue — это атрибут фиксированной длины, расположенный в таблице атрибутов структуры field_info. Если поле является статическим типом (т. е. в элементе access_flags структуры field_info установлен флаг ACC_STATIC), это означает, что постоянному значению поля, представленному структурой field_info, будет присвоено значение, представленное его атрибутом ConstantValue, который также является константой, объявленной классом или интерфейсом.Часть инициализации поля (константное поле). Этот процесс происходит перед выполнением метода инициализации класса или интерфейса, на который делается ссылка.
ConstantValue_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 constantvalue_index;
}
attribute_name_index
Значение элемента должно быть действительным индексом в пуле констант.attribute_length
Стоимость предмета зафиксирована на уровне 2.constantvalue_index
Значение элемента должно быть действительным индексом в пуле констант.
14.2 Свойство кода
Атрибут Code — это атрибут переменной длины, расположенный в таблице атрибутов структуры method_info. Атрибут Code сохраняет инструкции виртуальной машины Java и соответствующую вспомогательную информацию только для одного метода, метода инициализации класса экземпляра или метода инициализации класса. Все реализации виртуальных машин Java должны уметь распознавать свойство Code. Если метод объявлен как родной или абстрактный тип, соответствующая структура method_info не может иметь чистый атрибут 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];
}
attribute_name_index
Значение элемента должно быть допустимым индексом в пуле констант.attribute_length
Значение элемента указывает длину текущего атрибута, исключая первые 6 байтов.max_stack
Значение элемента дает максимальную глубину стека операндов текущего метода в любой момент времени выполнения.max_locals
Значение записи дает количество локальных переменных, выделенных в таблице локальных переменных, на которую ссылается текущий метод, включая локальные переменные, используемые для передачи аргументов при вызове этого метода. Максимальный индекс локальных переменных типа long и double равен max_locals-2, а максимальный индекс локальных переменных других типов — max_locals-1.code_length
Элемент дает количество байтов массива code[] текущего метода, а значение code_length должно быть больше 0, то есть массив code[] не может быть пустым.code[]
Массив дает байт-код виртуальной машины Java, реализующий текущий метод.exception_table_length
Значение термина даетexception_table[]
Количество членов массива.exception_table[]
Каждый элемент массива представляетcode[]
Обработчик исключений в массиве.exception_table[]
В массиве порядок обработчиков исключений имеет смысл (его нельзя изменить произвольно).start_pc
иend_pc
Значение двух элементов указывает допустимый диапазон обработчика исключений в массиве code[].handler_pc
элемент представляет начальную точку обработчика исключений
еслиcatch_type
элемент имеет значение, отличное от 0, тогда он должен быть допустимым индексом в пуле константattributes_count
Значение элемента дает количество членов таблицы атрибутов в свойстве Code.
Значение каждого члена таблицы атрибутов должно быть структурой атрибута. Свойство Code может иметь любое количество связанных с ним необязательных свойств.
14.3 Свойства StackMapTable
Свойство StackMapTable — это свойство переменной длины, расположенное в таблице свойств свойства Code. Это свойство используется на этапе загрузки класса виртуальной машины.
StackMapTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_entries;
stack_map_frame entries[number_of_entries];
}
attribute_name_index
Значение элемента должно быть допустимым индексом в пуле констант.attribute_length
Значение элемента указывает длину текущего атрибута, исключая первые 6 байтов.number_of_entries
Значение термина даетentries
Количество участников в таблице. Каждый член таблицы Entries являетсяstack_map_frame
Элементы конструкции.entries
В таблице указаны необходимыеstack_map_frame
структура.
... больше свойств здесь не размещено, их слишком много, просто проверьте официальную документацию, когда вам это нужно: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html #jvms-4.4
инструкции байт-кода
Инструкция виртуальной машины Java состоит из числа длиной в байт, представляющего значение конкретной операции (называемого кодом операции), за которым следуют операнды, представляющие параметры, необходимые для операции.
Длина кода операции составляет 1 байт, поэтому максимум составляет всего 256.
Постоянная инструкция push
Значение локальной переменной передается в стековую инструкцию
Сохранить верхнее значение стека в инструкции локальной переменной
широкая команда
Общие (нетипизированные) инструкции по работе со стеком
инструкция преобразования типа
Целочисленные операции
арифметика с плавающей запятой
Логические операции — операции сдвига
Логические операции — побитовые логические операции
Инструкции потока управления — инструкции условного перехода
Инструкции по управлению потоком — инструкции сравнения
Инструкции потока управления - инструкции безусловного перехода
Инструкции потока управления — Инструкции перехода к таблице
Инструкции потока управления - исключения и, наконец,
Инструкции по работе с объектами
инструкции по работе с массивом
инструкция вызова метода
инструкция возврата метода
инструкция синхронизации потоков
Ссылка на инструкцию: https://blog.csdn.net/web_code/article/details/12164733
Простой демонстрационный анализ
Test.java
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 20;
int c = a+b;
System.out.println(c);
}
}
javap -v Test.class
#2 = Fieldref #24.#25 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Methodref #26.#27 // java/io/PrintStream.println:(I)V
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: bipush 10 //把10扩展成int入栈
2: istore_1 //将栈顶int类型值保存到局部变量1中
3: bipush 20 //把20扩展成int入栈
5: istore_2 //将栈顶int类型值保存到局部变量2中
6: iload_1 //从局部变量1中装载int类型值入栈
7: iload_2 //从局部变量2中装载int类型值入栈
8: iadd // 将栈顶两int类型数相加,结果入栈。
9: istore_3 //将栈顶int类型值保存到局部变量3中
10: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;获取静态字段的值。#2表示常量池的索引
13: iload_3
14: invokevirtual #3 // Method java/io/PrintStream.println:(I)V 运行时方法绑定调用方法。
17: return //void函数返回。