Файл класса Java представляет собой файл (с .class расширением имени файла ) , содержащий Java - байт - код , который может быть выполнен на Java Virtual Machine (JVM) . Файл классов Java обычно создается компилятором Java из исходных файлов языка программирования Java ( файлов .java ), содержащих классы Java (в качестве альтернативы, для создания файлов классов также могут использоваться другие языки JVM ). Если исходный файл имеет более одного класса, каждый класс компилируется в отдельный файл класса.
Тип интернет-СМИ | приложение / java-vm, приложение / x-httpd-java |
---|---|
Разработано | Sun Microsystems |
JVM доступны для многих платформ , и файл класса, скомпилированный на одной платформе, будет выполняться на JVM другой платформы. Это делает Java-приложения независимыми от платформы .
История
11 декабря 2006 г. формат файла класса был изменен в соответствии с запросом спецификации Java (JSR) 202. [1]
Макет и структура файла
Разделы
Структура файла классов Java состоит из 10 основных разделов:
- Магическое число : 0xCAFEBABE
- Версия формата файла класса : младшая и основная версии файла класса
- Постоянный пул : пул констант для класса
- Флаги доступа : например, является ли класс абстрактным, статическим и т. Д.
- Этот класс : имя текущего класса.
- Суперкласс : Название суперкласса.
- Интерфейсы : любые интерфейсы в классе
- Поля : любые поля в классе.
- Методы : любые методы в классе.
- Атрибуты : любые атрибуты класса (например, имя исходного файла и т. Д.)
Магический номер
Файлы классов идентифицируются следующим 4- байтовым заголовком (в шестнадцатеричном формате ): CA FE BA BE
(первые 4 записи в таблице ниже). История этого магического числа была объяснена Джеймсом Гослингом со ссылкой на ресторан в Пало-Альто : [2]
«Раньше мы ходили обедать в место под названием St Michael's Alley. Согласно местной легенде, в глубоком темном прошлом Grateful Dead выступали там, прежде чем они добились успеха. Это было довольно забавное место, которое определенно было Grateful Dead Kinda Place. Когда Джерри умер, они даже построили маленькую святыню в буддийском стиле. Когда мы ходили туда, мы называли это место Cafe Dead. Где-то по ходу линии было замечено, что это был шестнадцатеричный номер. I. переделывал код формата файла и нуждался в паре магических чисел : одно для постоянного объектного файла и одно для классов. Я использовал CAFEDEAD для формата объектного файла и в grepping для 4-х символьных шестнадцатеричных слов, которые подходят после "CAFE "(казалось, это хорошая тема) Я натолкнулся на BABE и решил использовать его. В то время это не казалось ужасно важным или предназначенным никуда, кроме мусорного ведра истории. Так CAFEBABE стал файлом класса формат, а CAFEDEAD был форматом постоянного объекта. Но функция постоянного объекта перестала работать. да, а вместе с ним и использование CAFEDEAD - в конечном итоге он был заменен на RMI .
Генеральный план
Поскольку файл класса содержит элементы переменного размера и также не содержит встроенных файловых смещений (или указателей), он обычно анализируется последовательно, от первого байта до конца. На самом низком уровне формат файла описывается в терминах нескольких основных типов данных:
- u1 : 8-битное целое число без знака
- u2 : беззнаковое 16-битное целое число с прямым порядком байтов
- u4 : 32-битное целое число без знака с прямым порядком байтов
- таблица : массив элементов переменной длины некоторого типа. Количество элементов в таблице идентифицируется предыдущим числом счетчика (счетчик - u2), но размер в байтах таблицы может быть определен только путем изучения каждого из ее элементов.
Некоторые из этих фундаментальных типов затем повторно интерпретируются как значения более высокого уровня (например, строки или числа с плавающей запятой), в зависимости от контекста. Выравнивание слов не выполняется, поэтому байты заполнения никогда не используются. Общий вид файла класса показан в следующей таблице.
байтовое смещение | размер | тип или значение | описание |
---|---|---|---|
0 | 4 байта | u1 = 0xCA шестнадцатеричный | магическое число (CAFEBABE), используемое для идентификации файла как соответствующего формату файла класса |
1 | u1 = 0xFE шестнадцатеричный | ||
2 | u1 = 0xBA шестнадцатеричный | ||
3 | u1 = 0xBE шестнадцатеричный | ||
4 | 2 байта | u2 | младший номер версии используемого формата файла класса |
5 | |||
6 | 2 байта | u2 | номер основной версии используемого формата файла класса. Java SE 17 = 61 (0x3D шестнадцатеричный), |
7 | |||
8 | 2 байта | u2 | постоянный счетчик пула, количество записей в следующей постоянной пуловой таблице. Это количество как минимум на единицу больше, чем фактическое количество записей; см. следующее обсуждение. |
9 | |||
10 | cpsize (переменная) | Таблица | таблица пула констант, массив записей пула констант переменного размера, содержащий такие элементы, как буквальные числа, строки и ссылки на классы или методы. Индексируется, начиная с 1, и содержит ( постоянное количество пулов - 1) общее количество записей (см. Примечание). |
... | |||
... | |||
... | |||
10+ cpsize | 2 байта | u2 | флаги доступа, битовая маска |
11+ cpsize | |||
12+ cpsize | 2 байта | u2 | идентифицирует этот класс, индексирует в пуле констант запись типа "Class" |
13+ cpsize | |||
14+ cpsize | 2 байта | u2 | идентифицирует суперкласс , индексирует в постоянном пуле запись типа "Class" |
15+ cpsize | |||
16+ cpsize | 2 байта | u2 | количество интерфейсов, количество записей в следующей таблице интерфейсов |
17+ cpsize | |||
18+ cpsize | isize (переменная) | Таблица | таблица интерфейсов: массив переменной длины из индексов пула констант, описывающих интерфейсы, реализованные этим классом |
... | |||
... | |||
... | |||
18+ cpsize + isize | 2 байта | u2 | количество полей, количество записей в следующей таблице полей |
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 байта | u2 | количество методов, количество записей в следующей таблице методов |
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 байта | u2 | количество атрибутов, количество записей в следующей таблице атрибутов |
23+ cpsize + isize + fsize + msize | |||
24+ cpsize + isize + fsize + msize | asize (переменная) | Таблица | таблица атрибутов, массив атрибутов переменной длины каждый элемент представляет собой структуру attribute_info, определенную в https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7 |
... | |||
... | |||
... |
Представление на C-подобном языке программирования
Поскольку C не поддерживает несколько массивов переменной длины в структуре, приведенный ниже код не компилируется и служит только для демонстрации.
STRUCT Class_File_Format { U4 magic_number ; 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_count ]; u2 fields_count ; field_info fields [ количество_полей ]; u2 method_count ; method_info методы [ method_count ]; u2 attributes_count ; attribute_info атрибуты [ attribute_count ]; }
Постоянный бассейн
Таблица пула констант - это место, где хранится большинство буквальных значений констант. Сюда входят такие значения, как числа всех видов, строки, имена идентификаторов, ссылки на классы и методы и дескрипторы типов. Все индексы или ссылки на определенные константы в таблице пула констант задаются 16-битными числами (тип u2), где значение индекса 1 относится к первой константе в таблице (значение индекса 0 недопустимо).
Из-за исторического выбора, сделанного во время разработки формата файла, количество констант в таблице пула констант фактически не совпадает с количеством констант пула, которое предшествует таблице. Во-первых, таблица индексируется, начиная с 1 (а не с 0), но на самом деле счет должен интерпретироваться как максимальный индекс плюс один. [5] Кроме того, два типа констант (длинные и двойные) занимают два последовательных слота в таблице, хотя второй такой слот является фантомным индексом, который никогда не используется напрямую.
Тип каждого элемента (константы) в пуле констант определяется начальным байтовым тегом . Количество байтов, следующих за этим тегом, и их интерпретация зависят от значения тега. Допустимые типы констант и их значения тегов:
Байт тега | Дополнительные байты | Описание константы | Представленная версия |
---|---|---|---|
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 байта | Ссылка на поле: два индекса в пуле констант, первый указывает на ссылку на класс, второй - на дескриптор имени и типа. (с прямым порядком байтов) | 1.0.2 |
10 | 4 байта | Ссылка на метод: два индекса в пуле констант, первый указывает на ссылку на класс, второй - на дескриптор имени и типа. (с прямым порядком байтов) | 1.0.2 |
11 | 4 байта | Ссылка на метод интерфейса: два индекса в пуле констант, первый указывает на ссылку на класс, второй - на дескриптор имени и типа. (с прямым порядком байтов) | 1.0.2 |
12 | 4 байта | Дескриптор имени и типа: два индекса для строк UTF-8 в пуле констант, первый представляет имя (идентификатор), а второй - дескриптор специально закодированного типа. | 1.0.2 |
15 | 3 байта | Дескриптор метода: эта структура используется для представления описателя метода и состоит из одного байта дескриптора типа, за которым следует индекс в пуле констант. [5] | 7 |
16 | 2 байта | Тип метода: эта структура используется для представления типа метода и состоит из индекса в пуле констант. [5] | 7 |
17 | 4 байта | Динамический: используется для указания динамически вычисляемой константы, полученной при вызове метода начальной загрузки. [5] | 11 |
18 | 4 байта | InvokeDynamic: используется инструкцией invokedynamic для указания метода начальной загрузки, имени динамического вызова, аргументов и типов возвращаемых данных вызова и, необязательно, последовательности дополнительных констант, называемых статическими аргументами для метода начальной загрузки. [5] | 7 |
19 | 2 байта | Модуль: используется для идентификации модуля. [5] | 9 |
20 | 2 байта | Пакет: используется для идентификации пакета, экспортированного или открытого модулем. [5] | 9 |
Есть только два целочисленных типа констант: целочисленные и длинные. Другие целочисленные типы, встречающиеся в языке высокого уровня, такие как 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
.
Смотрите также
- Байт-код Java
Рекомендации
- ^ JSR 202 Обновление спецификации файла класса Java
- ^ Джеймс Гослинг частное сообщение Билл Бамгарнер
- ^ http://www.oracle.com/technetwork/java/javase/10-relnote-issues-4108729.html#Remaining
- ^ https://bugs.openjdk.java.net/browse/JDK-8148785
- ^ Б с д е е г https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.4
дальнейшее чтение
- Тим Линдхольм , Фрэнк Йеллин (1999). Спецификация виртуальной машины Java (второе изд.). Прентис Холл. ISBN 0-201-43294-3. Проверено 13 октября 2008 .Официальный определяющий документ виртуальной машины Java , который включает формат файла класса. И первое, и второе издания книги находятся в свободном доступе в Интернете для просмотра и / или загрузки .