Файл класса 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 ».
Поскольку файл класса содержит элементы переменного размера и не содержит встроенных смещений файлов (или указателей), он обычно анализируется последовательно, от первого байта к концу. На самом низком уровне формат файла описывается в терминах нескольких фундаментальных типов данных:
Некоторые из этих фундаментальных типов затем переинтерпретируются как значения более высокого уровня (например, строки или числа с плавающей точкой), в зависимости от контекста. Нет принудительного выравнивания слов, поэтому никакие байты заполнения никогда не используются. Общая структура файла класса показана в следующей таблице.
Поскольку язык программирования 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) занимают два последовательных слота в таблице, хотя второй такой слот является фантомным индексом, который никогда не используется напрямую.
Тип каждого элемента (константы) в константном пуле определяется начальным байтовым тегом . Количество байтов, следующих за этим тегом, и их интерпретация зависят от значения тега. Допустимые типы констант и их значения тегов:
Существует только два типа целочисленных констант: 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
.