Тип интернет-СМИ | приложение/java-vm, приложение/x-httpd-java, приложение/x-java, приложение/java, приложение/java-байт-код, приложение/x-java-класс, приложение/x-java-vm |
---|---|
Разработано | Sun Microsystems |
Файл класса Java — это файл (с расширением имени файла .class ), содержащий байт-код Java , который может быть выполнен на виртуальной машине Java (JVM) . Файл класса Java обычно создается компилятором Java из исходных файлов языка программирования Java ( файлов .java ), содержащих классы Java (в качестве альтернативы для создания файлов классов могут использоваться и другие языки JVM ). Если исходный файл содержит более одного класса, каждый класс компилируется в отдельный файл класса. Таким образом, он называется файлом .class , поскольку содержит байт-код для одного класса.
JVM доступны для многих платформ , и файл класса, скомпилированный на одной платформе, будет выполняться на JVM другой платформы. Это делает приложения Java платформенно-независимыми .
11 декабря 2006 года формат файла класса был изменен в соответствии с запросом спецификации Java (JSR) 202. [1]
Структура файла класса Java состоит из 10 основных разделов:
Файлы классов идентифицируются следующим 4- байтовым заголовком (в шестнадцатеричном формате ): CA FE BA BE
(первые 4 записи в таблице ниже). Историю этого магического числа объяснил Джеймс Гослинг, ссылаясь на ресторан в Пало-Альто : [2]
«Мы ходили обедать в место под названием St Michael's Alley. Согласно местной легенде, в далеком темном прошлом Grateful Dead выступали там, прежде чем добились успеха. Это было довольно необычное место, которое определенно было местом в духе Grateful Dead. Когда Джерри умер, они даже построили небольшую буддийскую святыню. Когда мы ходили туда, мы называли это место Cafe Dead. Где-то по ходу дела было замечено, что это число HEX. Я переделывал какой-то код формата файла и мне понадобилось несколько магических чисел : одно для постоянного объектного файла и одно для классов. Я использовал CAFEDEAD для формата объектного файла, и при поиске 4-символьных шестнадцатеричных слов, которые подходят после «CAFE» (казалось, это хорошая тема), я наткнулся на BABE и решил использовать его. В то время это не казалось таким уж важным или предназначенным куда-то, кроме как в мусорную корзину истории. Так CAFEBABE стал форматом файла класса, и CAFEDEAD был форматом постоянных объектов. Но возможность постоянных объектов ушла, и вместе с ней ушло и использование CAFEDEAD — в конечном итоге его заменил RMI ».
Поскольку файл класса содержит элементы переменного размера и не содержит встроенных смещений файлов (или указателей), он обычно анализируется последовательно, от первого байта к концу. На самом низком уровне формат файла описывается в терминах нескольких фундаментальных типов данных:
Некоторые из этих фундаментальных типов затем переинтерпретируются как значения более высокого уровня (например, строки или числа с плавающей точкой), в зависимости от контекста. Нет принудительного выравнивания слов, поэтому никакие байты заполнения никогда не используются. Общая структура файла класса показана в следующей таблице.
Смещение байта | Размер | Тип или значение | Описание |
---|---|---|---|
0 | 4 байта | u1 = 0xCA шестнадцатеричный | магическое число (CAFEBABE), используемое для идентификации файла как соответствующего формату файла класса |
1 | u1 = 0xFE шестнадцатеричный | ||
2 | u1 = 0xBA шестнадцатеричный | ||
3 | u1 = 0xBE шестнадцатеричный | ||
4 | 2 байта | у2 | дополнительный номер версии используемого формата файла класса |
5 | |||
6 | 2 байта | у2 | основной номер версии используемого формата файла класса. [3] Java SE 24 = 68 (шестнадцатеричное 0x44), |
7 | |||
8 | 2 байта | у2 | постоянный счет пула, количество записей в следующей таблице постоянного пула. Это количество по крайней мере на единицу больше фактического количества записей; см. следующее обсуждение. |
9 | |||
10 | cpsize (переменная) | стол | Таблица константного пула, массив записей константного пула переменного размера, содержащий такие элементы, как литеральные числа, строки и ссылки на классы или методы. Индексируется с 1, содержит ( число константного пула - 1) общее количество записей (см. примечание). |
... | |||
... | |||
... | |||
10+ cpsize | 2 байта | у2 | флаги доступа, битовая маска |
11+ размер cp | |||
12+ размер cp | 2 байта | у2 | идентифицирует этот класс, индекс в константном пуле для записи типа «Класс» |
13+ размер cp | |||
14+ размер cp | 2 байта | у2 | определяет суперкласс , индекс в константном пуле для записи типа «Класс» |
15+ размер | |||
16+ размер | 2 байта | у2 | количество интерфейсов, количество записей в следующей таблице интерфейсов |
17+ размер cp | |||
18+ размер cp | размер (переменная) | стол | таблица интерфейсов: массив переменной длины константных индексов пула, описывающих интерфейсы, реализованные этим классом |
... | |||
... | |||
... | |||
18+ cpsize + isize | 2 байта | у2 | количество полей, количество записей в следующей таблице полей |
19+ cpsize + isize | |||
20+ cpsize + isize | fsize (переменная) | стол | таблица полей, массив полей переменной длины каждый элемент представляет собой структуру field_info, определенную в https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5 |
... | |||
... | |||
... | |||
20+ cpsize + isize + fsize | 2 байта | у2 | количество методов, количество записей в следующей таблице методов |
21+ cpsize + isize + fsize | |||
22+ cpsize + isize + fsize | msize (переменная) | стол | таблица методов, массив методов переменной длины каждый элемент представляет собой структуру method_info, определенную в https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6 |
... | |||
... | |||
... | |||
22+ cpsize + isize + fsize + msize | 2 байта | у2 | количество атрибутов, количество записей в следующей таблице атрибутов |
23+ cpsize + isize + fsize + msize | |||
24+ cpsize + isize + fsize + msize | размер (переменная) | стол | таблица атрибутов, массив атрибутов переменной длины каждый элемент представляет собой структуру attribute_info, определенную в https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7 |
... | |||
... | |||
... |
Поскольку язык программирования C не поддерживает несколько массивов переменной длины внутри структуры, приведенный ниже код не будет компилироваться и служит только в качестве демонстрации.
структура Class_File_Format { u4 magic_number ; u2 второстепенная_версия ; u2 основная_версия ; u2 constant_pool_count ; cp_info constant_pool [ constant_pool_count - 1 ]; u2 флаги_доступа ; u2 этот_класс ; u2 супер_класс ; u2 interfaces_count ; интерфейсы u2 [ interfaces_count ]; u2 fields_count ; field_info поля [ fields_count ]; u2 methods_count ; method_info методы [ methods_count ]; u2 attribute_count ; attribute_info атрибуты [ attribute_count ]; }
Таблица константного пула — это место, где хранится большинство литеральных константных значений. Сюда входят такие значения, как числа всех видов, строки, имена идентификаторов, ссылки на классы и методы, а также дескрипторы типов. Все индексы или ссылки на конкретные константы в таблице константного пула задаются 16-битными числами (тип u2), где значение индекса 1 относится к первой константе в таблице (значение индекса 0 недопустимо).
Из-за исторических выборов, сделанных во время разработки формата файла, количество констант в таблице пула констант на самом деле не совпадает с количеством пулов констант, которое предшествует таблице. Во-первых, таблица индексируется, начиная с 1 (а не с 0), но количество фактически должно интерпретироваться как максимальный индекс плюс один. [6] Кроме того, два типа констант (long и double) занимают два последовательных слота в таблице, хотя второй такой слот является фантомным индексом, который никогда не используется напрямую.
Тип каждого элемента (константы) в константном пуле определяется начальным байтовым тегом . Количество байтов, следующих за этим тегом, и их интерпретация зависят от значения тега. Допустимые типы констант и их значения тегов:
Тег байта | Дополнительные байты | Описание константы | Представлена версия |
---|---|---|---|
1 | 2+ x байт (переменная) | Строка UTF-8 (Unicode): строка символов, начинающаяся с 16-битного числа (тип u2), указывающего количество байтов в закодированной строке, которая следует сразу за ней (которое может отличаться от количества символов). Обратите внимание, что используемая кодировка на самом деле не UTF-8 , а представляет собой небольшую модификацию стандартной формы кодировки Unicode. | 1.0.2 |
3 | 4 байта | Целое число: 32-битное число со знаком в формате дополнения до двух в формате big-endian. | 1.0.2 |
4 | 4 байта | Float: 32-битное число с плавающей точкой одинарной точности IEEE 754. | 1.0.2 |
5 | 8 байт | Длинное: знаковое 64-битное число в формате дополнения до двух в формате big-endian (занимает два слота в таблице константного пула) | 1.0.2 |
6 | 8 байт | Double: 64-битное число с плавающей точкой двойной точности IEEE 754 (занимает два слота в таблице константного пула) | 1.0.2 |
7 | 2 байта | Ссылка на класс: индекс в константном пуле на строку UTF-8, содержащую полное имя класса (во внутреннем формате ) (с обратным порядком байтов) | 1.0.2 |
8 | 2 байта | Ссылка на строку: индекс в константном пуле на строку UTF-8 (также с обратным порядком байтов) | 1.0.2 |
9 | 4 байта | Ссылка на поле: два индекса в константном пуле, первый указывает на ссылку на класс, второй — на дескриптор имени и типа. (big-endian) | 1.0.2 |
10 | 4 байта | Ссылка на метод: два индекса в константном пуле, первый указывает на ссылку на класс, второй — на дескриптор имени и типа. (big-endian) | 1.0.2 |
11 | 4 байта | Ссылка на метод интерфейса: два индекса в константном пуле, первый указывает на ссылку класса, второй — на дескриптор имени и типа. (big-endian) | 1.0.2 |
12 | 4 байта | Имя и дескриптор типа: два индекса для строк UTF-8 в пуле констант, первый из которых представляет имя (идентификатор), а второй — специально закодированный дескриптор типа. | 1.0.2 |
15 | 3 байта | Дескриптор метода: эта структура используется для представления дескриптора метода и состоит из одного байта дескриптора типа, за которым следует индекс в константном пуле. [6] | 7 |
16 | 2 байта | Тип метода: эта структура используется для представления типа метода и состоит из индекса в константном пуле. [6] | 7 |
17 | 4 байта | Динамический: используется для указания динамически вычисляемой константы, создаваемой путем вызова метода начальной загрузки. [6] | 11 |
18 | 4 байта | InvokeDynamic: используется инструкцией invokedynamic для указания метода начальной загрузки, имени динамического вызова, типов аргумента и возвращаемого значения вызова, а также, опционально, последовательности дополнительных констант, называемых статическими аргументами метода начальной загрузки. [6] | 7 |
19 | 2 байта | Модуль: используется для идентификации модуля. [6] | 9 |
20 | 2 байта | Пакет: используется для идентификации пакета, экспортированного или открытого модулем. [6] | 9 |
Существует только два типа целочисленных констант: integer и long. Другие целочисленные типы, появляющиеся в языке высокого уровня, такие как boolean, byte и short, должны быть представлены как целочисленная константа.
Имена классов в Java, если они полностью определены, традиционно разделяются точками, например, "java.lang.Object". Однако в константах ссылок на класс низкого уровня появляется внутренняя форма, которая вместо этого использует слеши, например, "java/lang/Object".
Строки Unicode, несмотря на прозвище "строка UTF-8", на самом деле не кодируются в соответствии со стандартом Unicode, хотя это похоже. Есть два отличия (см. UTF-8 для полного обсуждения). Первое заключается в том, что кодовая точка U+0000 кодируется как двухбайтовая последовательность C0 80
(в шестнадцатеричном виде) вместо стандартной однобайтовой кодировки 00
. Второе отличие заключается в том, что дополнительные символы (те, которые находятся вне BMP при U+10000 и выше) кодируются с использованием конструкции суррогатной пары, похожей на UTF-16 , а не напрямую кодируются с использованием UTF-8. В этом случае каждый из двух суррогатов кодируется отдельно в UTF-8. Например, U+1D11E кодируется как 6-байтовая последовательность ED A0 B4 ED B4 9E
, а не как правильная 4-байтовая кодировка UTF-8 F0 9D 84 9E
.