Исполняемый формат Dalvik

В этом документе описаны структура и содержимое файлов .dex, в которых хранятся определения классов и связанные с ними дополнительные данные.

Руководство по типам

Название Описание
байт 8-битное целое число со знаком
ubyte 8-битное целое число без знака
короткое видео 16-битное целое число со знаком, младший байт в начале
ushort 16-битное целое число без знака, порядок байтов от младшего к старшему
ПРХВ 32-разрядное целое число со знаком, младший байт в начале
uint 32-разрядное целое число без знака, little-endian
long 64-разрядное целое число со знаком, little-endian
улун 64-разрядное целое число без знака, little-endian
sleb128 signed LEB128, переменная длина (см. ниже)
uleb128 unsigned LEB128, переменная длина (см. ниже)
uleb128p1 беззнаковое LEB128 плюс 1, переменная длина (см. ниже)

LEB128

LEB128 (Little-Endian Base 128) – это кодировка переменной длины для произвольных целых чисел со знаком или без знака. Формат заимствован из спецификации DWARF3. В файле .dex кодировка LEB128 используется только для 32-битных значений.

Каждое значение, закодированное с помощью LEB128, состоит из одного–пяти байтов, которые вместе представляют одно 32-битное значение. У каждого байта установлен старший бит, за исключением последнего байта в последовательности, у которого старший бит очищен. Остальные семь битов каждого байта содержат полезную нагрузку: семь младших битов – в первом байте, следующие семь – во втором и т. д. В случае с LEB128 со знаком (sleb128) старший бит полезной нагрузки последнего байта в последовательности расширяется до знака, чтобы получить конечное значение. В случае без знака (uleb128) любые биты, не представленные явно, интерпретируются как 0.

Побитовая диаграмма двухбайтового значения LEB128
Первый байт Второй байт
1 бит 6 bit5 bit4 bit3 bit2 бит1 bit0 0 bit13 bit12 bit11 bit10 bit9 bit8 bit7

Вариант uleb128p1 используется для представления значения со знаком, где значение плюс один закодировано как uleb128. Это позволяет закодировать -1 (или 0xffffffff) одним байтом, но не другие отрицательные числа. Это полезно в тех случаях, когда представляемое число должно быть неотрицательным или равным -1 (или 0xffffffff) и когда другие отрицательные значения недопустимы (или когда вряд ли понадобятся большие неотрицательные значения).

Вот несколько примеров:

Закодированная последовательность Как sleb128 Как uleb128 Как uleb128p1
0000-1
01110
7f-1127126
80 7f-1281625616255

Макет файла

Название Формат Описание
заголовок header_item заголовок;
string_ids string_id_item[] список идентификаторов строк. Это идентификаторы всех строк, используемых в файле, как для внутреннего именования (например, дескрипторов типов), так и в качестве постоянных объектов, на которые ссылается код. Этот список должен быть отсортирован по содержимому строк с использованием значений кодовых точек UTF-16 (без учета локали) и не должен содержать повторяющихся записей.
type_ids type_id_item[] список идентификаторов типов. Идентификаторы всех типов (классов, массивов или примитивных типов), на которые ссылается этот файл, независимо от того, определены они в файле или нет. Список должен быть отсортирован по индексу string_id и не содержать повторяющихся записей.
proto_ids proto_id_item[] список идентификаторов прототипов методов. Идентификаторы всех прототипов, на которые ссылается этот файл. Этот список должен быть отсортирован по типу возвращаемого значения (по индексу type_id) в порядке убывания, а затем по списку аргументов (в лексикографическом порядке, отдельные аргументы упорядочены по индексу type_id). Список не должен содержать повторяющихся записей.
field_ids field_id_item[] список идентификаторов полей. Это идентификаторы всех полей, на которые ссылается файл, независимо от того, определены они в файле или нет. Этот список должен быть отсортирован по определяющему типу (индекс type_id), названию поля (индекс string_id) и типу (индекс type_id). В списке не должно быть повторяющихся записей.
method_ids method_id_item[] список идентификаторов методов. Это идентификаторы всех методов, на которые ссылается файл, независимо от того, определены они в файле или нет. Этот список должен быть отсортирован. Определяющий тип (по индексу type_id) – это основной порядок, название метода (по индексу string_id) – промежуточный порядок, а прототип метода (по индексу proto_id) – дополнительный порядок. Список не должен содержать повторяющихся записей.
class_defs class_def_item[] список определений классов. Классы должны быть упорядочены таким образом, чтобы надкласс и реализованные интерфейсы данного класса появлялись в списке раньше, чем ссылающийся класс. Кроме того, недопустимо, чтобы определение класса с одним и тем же названием появлялось в списке более одного раза.
call_site_ids call_site_id_item[] вызовите список идентификаторов сайтов. Это идентификаторы всех сайтов вызовов, на которые ссылается этот файл, независимо от того, определены они в файле или нет. Этот список должен быть отсортирован по возрастанию значения call_site_off.
method_handles method_handle_item[] список обработчиков методов. Список всех дескрипторов методов, на которые ссылается этот файл, независимо от того, определены они в файле или нет. Этот список не отсортирован и может содержать дубликаты, которые логически соответствуют разным экземплярам дескриптора метода.
данные ubyte[] область данных, содержащую все вспомогательные данные для перечисленных выше таблиц. У разных объектов разные требования к выравниванию, и при необходимости перед каждым объектом вставляются байты заполнения, чтобы обеспечить правильное выравнивание.
link_data ubyte[] данные, используемые в статически связанных файлах. Формат данных в этом разделе не указан в этом документе. В несвязанных файлах этот раздел пуст, и реализации среды выполнения могут использовать его по своему усмотрению.

Формат контейнера

В версии 41 представлен новый формат контейнера для данных DEX, который позволяет экономить место. Этот формат контейнера позволяет объединить несколько логических файлов DEX в один физический файл. Новый формат – это в основном простое объединение файлов предыдущего формата с некоторыми отличиями:

  • file_size – это размер логического файла, а не физического. Его можно использовать для итерации по всем логическим файлам в контейнере.
  • Логические DEX-файлы могут ссылаться на любые более поздние данные в контейнере (но не на более ранние). Это позволяет файлам DEX обмениваться данными, например строками.
  • Все смещения указываются относительно физического файла. Смещение относительно заголовка не задано. Это позволяет использовать разделы со смещениями в разных логических файлах.
  • В заголовок добавлены два новых поля, описывающих границы контейнера. Это дополнительная проверка на согласованность, которая упрощает перенос кода в новый формат.
  • data_size и data_off больше не используются. Данные могут быть распределены по нескольким логическим файлам и не обязательно должны быть непрерывными.

Определения битовых полей, строк и констант

DEX_FILE_MAGIC

Встроено в header_item

Постоянный массив/строка DEX_FILE_MAGIC – это список байтов, которые должны быть в начале файла .dex, чтобы он был распознан как таковой. Значение намеренно содержит символ новой строки ("\n" или 0x0a) и нулевой байт ("\0" или 0x00), чтобы помочь в обнаружении определенных форм повреждения. Значение также содержит номер версии формата в виде трех десятичных цифр, который должен монотонно увеличиваться со временем по мере развития формата.

ubyte[8] DEX_FILE_MAGIC = { 0x64 0x65 0x78 0x0a 0x30 0x33 0x39 0x00 }
                        = "dex\n039\0"

Примечание. Поддержка версии 041 формата является экспериментальной в Android 16 и предназначена для тестирования формата контейнера. Однако версию 041 не следует использовать в рабочем коде.

Примечание. Поддержка версии 040 формата была добавлена в Android 10.0. В этой версии был расширен набор допустимых символов в простых именах.

Примечание. Поддержка версии 039 формата была добавлена в Android 9.0. В этой версии появились два новых байт-кода:const-method-handle и const-method-type. (Каждый из них описан в таблице Сводка набора байт-кода.) В Android 10 версия 039 расширяет формат DEX-файлов, добавляя в него скрытую информацию об API, которая применима только к DEX-файлам в пути загрузочного класса.

Примечание. Поддержка версии 038 этого формата была добавлена в Android 8.0. В версии 038 добавлены новые байт-коды (invoke-polymorphic и invoke-custom) и данные для дескрипторов методов.

Примечание. Поддержка формата версии 037 была добавлена в Android 7.0. До версии 037 в большинстве версий Android использовался формат версии 035. Единственное отличие версий 035 и 037 – это добавление методов по умолчанию и изменение invoke.

Примечание. В общедоступных версиях ПО использовались по крайней мере две более ранние версии формата. Например, версия 009 использовалась для выпусков M3 платформы Android (ноябрь–декабрь 2007 г.), а версия 013 – для выпусков M5 платформы Android (февраль–март 2008 г.). В некоторых отношениях эти более ранние версии формата значительно отличаются от версии, описанной в этом документе.

ENDIAN_CONSTANT и REVERSE_ENDIAN_CONSTANT

Встроено в header_item

Константа ENDIAN_CONSTANT используется для указания порядка байтов в файле, в котором она находится. Хотя стандартный формат .dex использует порядок байтов от младшего к старшему, в реализациях может быть выбран другой порядок. Если при реализации встречается заголовок, в котором endian_tag имеет значение REVERSE_ENDIAN_CONSTANT, а не ENDIAN_CONSTANT, то становится понятно, что файл был преобразован из ожидаемого формата.

uint ENDIAN_CONSTANT = 0x12345678;
uint REVERSE_ENDIAN_CONSTANT = 0x78563412;

NO_INDEX

Встроен в class_def_item и debug_info_item

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

Примечание. Это значение не может быть равно 0, поскольку это обычно допустимый индекс.

Значение параметра NO_INDEX можно представить в виде одного байта в кодировке uleb128p1.

uint NO_INDEX = 0xffffffff;    // == -1 if treated as a signed int

Определения access_flags

Встроено в class_def_item, encoded_field, encoded_method и InnerClass.

Битовые поля этих флагов используются для указания доступности и общих свойств классов и членов классов.

Название Значение Для классов (и аннотаций InnerClass) Для полей Для методов
ACC_PUBLIC 0x1 public: видно всем public: виден везде. public: видно всем
ACC_PRIVATE 0x2 * private: видно только определяющему классу. private: виден только в определяющем классе. private: видно только определяющему классу
ACC_PROTECTED 0x4 * protected: видно пакету и подклассам. protected: видно пакету и подклассам protected: доступно для пакета и подклассов.
ACC_STATIC 0x8 * static: не содержит внешнюю ссылку this static: глобальный в определяющий класс static: не принимает аргумент this
ACC_FINAL 0x10 final: нельзя создать подкласс final: нельзя изменить после создания final: нельзя переопределить
ACC_SYNCHRONIZED 0x20     synchronized: связанная блокировка автоматически получена во время вызова этого метода.

Примечание. Этот параметр можно задать, только если также задан параметр ACC_NATIVE.

ACC_VOLATILE 0x40   volatile: специальные правила доступа для обеспечения безопасности потоков;  
ACC_BRIDGE 0x40     bridge method, added automatically by compiler as a type-safe bridge
ACC_TRANSIENT 0x80   transient: не сохраняется при сериализации по умолчанию  
ACC_VARARGS 0x80     Последний аргумент должен обрабатываться компилятором как аргумент "rest".
ACC_NATIVE 0x100     native: реализовано в нативном коде
ACC_INTERFACE 0x200 interface: абстрактный класс с множественной реализацией    
ACC_ABSTRACT 0x400 abstract: нельзя создать экземпляр напрямую   abstract: не реализовано в этом классе
ACC_STRICT 0x800     strictfp: строгие правила для арифметики с плавающей запятой
ACC_SYNTHETIC 0x1000 не определено непосредственно в исходном коде не определено непосредственно в исходном коде; не определено непосредственно в исходном коде;
ACC_ANNOTATION 0x2000 объявлен как класс аннотаций;    
ACC_ENUM 0x4000 объявлено как перечисляемый тип объявлено как перечисляемое значение  
(не используется) 0x8000      
ACC_CONSTRUCTOR 0x10000     метод конструктора (инициализатор класса или экземпляра)
ACC_DECLARED_
SYNCHRONIZED
0x20000     объявлено synchronized.

Примечание. Это не влияет на выполнение (кроме отражения этого флага как такового).

* Допустимо только для аннотаций InnerClass и недопустимо для аннотаций class_def_item.

Модифицированная кодировка UTF-8

Чтобы упростить поддержку устаревших систем, формат .dex кодирует строковые данные в модифицированной форме UTF-8, которая является стандартом де-факто и далее будет называться MUTF-8. Эта форма идентична стандартной UTF-8, за исключением следующего:

  • Используются только одно-, двух- и трехбайтные кодировки.
  • Кодовые точки в диапазоне U+10000…U+10ffff кодируются как суррогатная пара, каждый элемент которой представлен в виде трехбайтового закодированного значения.
  • Кодовая точка U+0000 кодируется в двухбайтовом формате.
  • Простой нулевой байт (значение 0) указывает на конец строки, как это принято в языке C.

Первые два пункта можно обобщить следующим образом: MUTF-8 – это формат кодирования для UTF-16, а не более прямой формат кодирования для символов Unicode.

Два последних пункта позволяют одновременно включать кодовую точку U+0000 в строку и по-прежнему обрабатывать ее как строку с нулевым символом в конце в стиле C.

Однако специальная кодировка U+0000 означает, что, в отличие от обычного UTF-8, результат вызова стандартной функции C strcmp() для пары строк MUTF-8 не всегда указывает на правильный результат сравнения неравных строк. Если при сравнении строк MUTF-8 важен порядок символов (а не только их равенство), проще всего декодировать строки посимвольно и сравнивать декодированные значения. (Однако возможны и более сложные реализации.)

Дополнительную информацию о кодировке символов можно найти в стандарте Юникод. MUTF-8 ближе к менее известной кодировке CESU-8, чем к UTF-8.

encoded_value encoding

Вложен в annotation_element и encoded_array_item

encoded_value – это закодированный фрагмент (почти) произвольных иерархически структурированных данных. Кодировка должна быть компактной и простой для анализа.

Название Формат Описание
(value_arg << 5) | value_type ubyte байт, указывающий тип следующего за ним элемента value, а также необязательный уточняющий аргумент в трех старших битах. Ниже приведены определения различных типов value. В большинстве случаев value_arg кодирует длину следующего за ним параметра value в байтах как (size - 1), например 0 означает, что значение требует одного байта, а 7 – восьми. Однако есть исключения, указанные ниже.
значение ubyte[] байты, представляющие значение, переменной длины и интерпретируемые по-разному для разных байтов value_type, хотя всегда с прямым порядком байтов. Подробную информацию о различных значениях можно найти ниже.

Форматы значений

Название типа value_type Формат value_arg Формат value Описание
VALUE_BYTE 0x00 (нет; должно быть 0) ubyte[1] значение однобайтового целого числа со знаком
VALUE_SHORT 0x02 size - 1 (0…1) ubyte[size] знаковое двухбайтовое целое число, расширенное знаком
VALUE_CHAR 0x03 size - 1 (0…1) ubyte[size] беззнаковое двухбайтовое целое число, дополненное нулями
VALUE_INT 0x04 size – 1 (0…3); ubyte[size] четырехбайтовое целое число со знаком, расширенное знаком
VALUE_LONG 0x06 size – 1 (0…7); ubyte[size] восьмибайтное целое число со знаком, расширенное до знака;
VALUE_FLOAT 0x10 size – 1 (0…3); ubyte[size] четырехбайтовый битовый шаблон, дополненный нулями справа и интерпретируемый как 32-битное значение с плавающей запятой IEEE754;
VALUE_DOUBLE 0x11 size – 1 (0…7); ubyte[size] восьмибайтовый битовый шаблон, дополненный нулями справа и интерпретируемый как 64-битовое значение с плавающей запятой в формате IEEE754;
VALUE_METHOD_TYPE 0x15 size - 1 (0…3) ubyte[size] четырехбайтовое целое число без знака (дополненное нулями), которое интерпретируется как индекс в разделе proto_ids и представляет собой значение типа метода;
VALUE_METHOD_HANDLE 0x16 size - 1 (0…3) ubyte[size] Беззнаковое (с расширением нулями) четырехбайтовое целое число, которое интерпретируется как индекс в разделе method_handles и представляет значение дескриптора метода.
VALUE_STRING 0x17 size – 1 (0…3); ubyte[size] четырехбайтовое целое число без знака (дополненное нулями), которое интерпретируется как индекс в разделе string_ids и представляет строковое значение;
VALUE_TYPE 0x18 size - 1 (0…3) ubyte[size] четырехбайтовое целое число без знака (дополненное нулями), которое интерпретируется как индекс в разделе type_ids и представляет рефлексивное значение типа/класса;
VALUE_FIELD 0x19 size – 1 (0…3); ubyte[size] четырехбайтовое целое число без знака (дополненное нулями), которое интерпретируется как индекс в разделе field_ids и представляет значение рефлексивного поля;
VALUE_METHOD 0x1a size – 1 (0…3); ubyte[size] четырехбайтовое целое число без знака (дополненное нулями), которое интерпретируется как индекс в разделе method_ids и представляет значение рефлексивного метода;
VALUE_ENUM 0x1b size – 1 (0…3); ubyte[size] четырехбайтовое целое число без знака (дополненное нулями), которое интерпретируется как индекс в разделе field_ids и представляет значение константы перечисляемого типа;
VALUE_ARRAY 0x1c (нет; должно быть 0) encoded_array массив значений в формате, указанном в разделе "encoded_array format" ниже. Размер value неявно задан в кодировке.
VALUE_ANNOTATION 0x1d (нет; должно быть 0) encoded_annotation дополнительную аннотацию в формате, указанном в разделе "encoded_annotation format" ниже. Размер value определяется кодировкой.
VALUE_NULL 0x1e (нет; должно быть 0) (нет) null – справочное значение.
VALUE_BOOLEAN 0x1f Логическое значение (0…1) (none) Однобитное значение: 0 для false и 1 для true. Бит представлен в value_arg.

Формат encoded_array

Название Формат Описание
размер uleb128 количество элементов в массиве.
values encoded_value[size] последовательность байтов size encoded_value в формате, указанном в этом разделе, объединенных последовательно.

Формат encoded_annotation

Название Формат Описание
type_idx uleb128 тип аннотации. Это должен быть тип класса (не массив или примитив).
размер uleb128 количество сопоставлений пар "имя-значение" в этой аннотации;
элементы annotation_element[size] элементы аннотации, представленные непосредственно в строке (не в виде смещений). Элементы должны быть отсортированы по возрастанию индекса string_id.

Формат элемента аннотации

Название Формат Описание
name_idx uleb128 название элемента, представленное в виде индекса в разделе string_ids. Строка должна соответствовать синтаксису MemberName, описанному выше.
значение encoded_value значение элемента

Синтаксис строк

В файле .dex есть несколько типов элементов, которые в конечном итоге ссылаются на строку. Ниже приведены определения в стиле БНФ, которые указывают на допустимый синтаксис для этих строк.

SimpleName

Простое имя – это основа для синтаксиса имен других объектов. Формат .dex допускает значительную свободу действий (гораздо большую, чем большинство распространенных исходных языков). Простое имя состоит из любых букв или цифр из набора ASCII, нескольких определенных символов из этого набора и большинства кодовых точек, не входящих в него, за исключением управляющих, специальных символов и пробелов. Начиная с версии 040 формат также поддерживает пробелы (категория Unicode Zs ). Обратите внимание, что суррогатные кодовые точки (в диапазоне U+d800…U+dfff) не считаются допустимыми символами имени, но дополнительные символы Unicode являются допустимыми (они представлены в последней альтернативе правила для SimpleNameChar) и должны быть представлены в файле как пары суррогатных кодовых точек в кодировке MUTF-8.

SimpleName →
SimpleNameChar (SimpleNameChar)*
SimpleNameChar →
'A' … 'Z'
| 'a' … 'z'
| '0' … '9'
| ' ' начиная с версии DEX 040
| '$'
| '-'
| '_'
| U+00a0 начиная с версии DEX 040
| U+00a1 … U+1fff
| U+2000 … U+200a начиная с версии DEX 040;
| U+2010 … U+2027
| U+202f начиная с версии DEX 040
| U+2030 … U+d7ff
| U+e000 … U+ffef
| U+10000 … U+10ffff

MemberName

используется field_id_item и method_id_item

MemberName – это имя члена класса, которым может быть поле, метод или внутренний класс.

MemberName →
SimpleName
| '<' SimpleName '>'

FullClassName

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

FullClassName →
OptionalPackagePrefix SimpleName
OptionalPackagePrefix →
(SimpleName '/')*

TypeDescriptor

Используется type_id_item

TypeDescriptor – это представление любого типа, включая примитивы, классы, массивы и void. Ниже приведено описание разных версий.

TypeDescriptor →
'V'
| FieldTypeDescriptor
FieldTypeDescriptor →
NonArrayFieldTypeDescriptor
| ('[' * 1…255) NonArrayFieldTypeDescriptor
NonArrayFieldTypeDescriptor→
'Z'
| 'B'
| 'S'
| 'C'
| 'I'
| 'J'
| 'F'
| 'D'
| 'L' FullClassName ';'

ShortyDescriptor

Используется в proto_id_item

ShortyDescriptor – это краткое представление прототипа метода, включающее типы возвращаемых значений и параметров, за исключением того, что в нем не различаются разные типы ссылок (классов или массивов). Вместо этого все типы ссылок представлены одним символом 'L'.

ShortyDescriptor →
ShortyReturnType (ShortyFieldType)*
ShortyReturnType →
'V'
| ShortyFieldType
ShortyFieldType →
'Z'
| 'B'
| 'S'
| 'C'
| 'I'
| 'J'
| 'F'
| 'D'
| 'L'

Семантика TypeDescriptor

Ниже приведено значение каждого варианта TypeDescriptor.

Синтаксис Значение
V void – только для типов возвращаемого значения.
Z boolean
B byte
С short
C char
I int
J long
F float
Д double
Lfully/qualified/Name; курс fully.qualified.Name;
[дескриптор массив descriptor, который можно использовать рекурсивно для массивов массивов, хотя недопустимо иметь более 255 измерений.

Объекты и связанные структуры

В этом разделе приведены определения всех элементов верхнего уровня, которые могут быть в файле .dex.

header_item

Отображается в разделе заголовка

Выравнивание: 4 байта.

Название Формат Описание
волшебный ubyte[8] = DEX_FILE_MAGIC волшебное значение. Подробную информацию можно найти в разделе DEX_FILE_MAGIC выше.
контрольная сумма uint Контрольная сумма adler32 для остальной части файла (всего, кроме magic и этого поля). Используется для обнаружения повреждений файла.
подпись ubyte[20] Подпись (хеш) SHA-1 остальной части файла (всего, кроме magic, checksum и этого поля). Используется для уникальной идентификации файлов.
file_size uint

размер всего файла (включая заголовок) в байтах. (версия 40 или более ранняя)

расстояние в байтах от начала этого заголовка до следующего заголовка или до конца всего файла (контейнера). (v41 или более поздняя версия)

header_size uint

Размер заголовка (всего этого раздела) в байтах. Это позволяет обеспечить хотя бы ограниченную обратную и прямую совместимость без нарушения формата.

должен составлять 0x70 (112) байт. (версия 40 или более ранняя)

должен составлять 120 байт (0x78). (версия 41 или более поздняя)

endian_tag uint = ENDIAN_CONSTANT тег endianness; Подробнее об этом рассказывается в разделе "ENDIAN_CONSTANT и REVERSE_ENDIAN_CONSTANT".
link_size uint размер раздела ссылок или 0, если файл не связан статически.
link_off uint смещение от начала файла до раздела ссылки или 0, если link_size == 0. Смещение, если оно не равно нулю, должно быть смещением в разделе link_data. Формат данных, на которые указывает этот заголовок, не определен в этом документе. Это поле заголовка (как и предыдущее) оставлено в качестве точки подключения для использования в реализациях во время выполнения.
map_off uint смещение от начала файла до объекта карты. Смещение должно быть ненулевым и указывать на раздел data. Данные должны быть в формате, указанном ниже в разделе map_list.
string_ids_size uint количество строк в списке идентификаторов строк;
string_ids_off uint смещение от начала файла до списка идентификаторов строк или 0, если string_ids_size == 0 (довольно странный пограничный случай). Если смещение не равно нулю, оно должно указывать на начало раздела string_ids.
type_ids_size uint количество элементов в списке идентификаторов типов, не более 65 535;
type_ids_off uint смещение от начала файла до списка идентификаторов типов или 0, если type_ids_size == 0 (довольно странный пограничный случай). Если смещение не равно нулю, оно должно быть относительно начала раздела type_ids.
proto_ids_size uint количество элементов в списке идентификаторов прототипов (не более 65 535);
proto_ids_off uint смещение от начала файла до списка идентификаторов прототипов или 0, если proto_ids_size == 0 (довольно странный пограничный случай). Если смещение не равно нулю, оно должно быть относительно начала раздела proto_ids.
field_ids_size uint количество элементов в списке идентификаторов полей;
field_ids_off uint Смещение от начала файла до списка идентификаторов полей или 0, если field_ids_size == 0. Если смещение не равно нулю, оно должно быть относительно начала раздела field_ids.
method_ids_size uint количество элементов в списке идентификаторов методов;
method_ids_off uint смещение от начала файла до списка идентификаторов методов или 0, если method_ids_size == 0. Если смещение не равно нулю, оно должно быть относительно начала раздела method_ids.
class_defs_size uint количество элементов в списке определений классов;
class_defs_off uint смещение от начала файла до списка определений классов или 0, если class_defs_size == 0 (довольно странный крайний случай). Если смещение не равно нулю, оно должно быть относительно начала раздела class_defs.
data_size uint

Размер раздела data в байтах. Должен быть четным числом, кратным sizeof(uint). (v40 или более ранние версии)

Не используется (v41 или более поздняя версия)

data_off uint

смещение от начала файла до начала раздела data(версия 40 или более ранняя)

Не используется (версия 41 или более поздняя)

container_size uint

этого поля не существует. Можно предположить, что оно равно file_size. (версия 40 или более ранняя)

размер всего файла (включая другие заголовки DEX и их данные). (версия 41 или более поздняя)

header_offset uint

этого поля не существует. Можно предположить, что оно равно 0. (v40 или более ранней версии)

смещение от начала файла до начала этого заголовка. (версия 41 или более поздняя)

map_list

Показывается в разделе данных

Указано в заголовке header_item

Выравнивание: 4 байта.

Это список всего содержимого файла в том порядке, в котором оно представлено в файле. Он частично дублирует header_item, но предназначен для удобного перебора всего файла. Один тип может встречаться в карте не более одного раза.Порядок типов не ограничен, за исключением ограничений, подразумеваемых остальными элементами формата (например, раздел header должен идти первым, за ним – раздел string_ids и т. д.). Кроме того, записи в карте должны быть упорядочены по начальному смещению и не должны перекрываться.

Название Формат Описание
размер uint размер списка в записях;
list map_item[size] элементы списка;

Формат map_item

Название Формат Описание
тип ushort Тип объектов (см. таблицу ниже).
unused ushort (не используется)
размер uint количество объектов, которые нужно найти по указанному смещению;
вычесть uint смещение от начала файла до нужных объектов;

Введите коды

Тип продукта Константа Значение Размер объекта в байтах
header_item TYPE_HEADER_ITEM 0x0000 0x70
string_id_item TYPE_STRING_ID_ITEM 0x0001 0x04
type_id_item TYPE_TYPE_ID_ITEM 0x0002 0x04
proto_id_item TYPE_PROTO_ID_ITEM 0x0003 0x0c
field_id_item TYPE_FIELD_ID_ITEM 0x0004 0x08
method_id_item TYPE_METHOD_ID_ITEM 0x0005 0x08
class_def_item TYPE_CLASS_DEF_ITEM 0x0006 0x20
call_site_id_item TYPE_CALL_SITE_ID_ITEM 0x0007 0x04
method_handle_item TYPE_METHOD_HANDLE_ITEM 0x0008 0x08
map_list TYPE_MAP_LIST 0x1000 4 + (item.size * 12)
type_list TYPE_TYPE_LIST 0x1001 4 + (item.size * 2)
annotation_set_ref_list TYPE_ANNOTATION_SET_REF_LIST 0x1002 4 + (item.size * 4)
annotation_set_item TYPE_ANNOTATION_SET_ITEM 0x1003 4 + (item.size * 4)
class_data_item TYPE_CLASS_DATA_ITEM 0x2000 неявный; необходимо проанализировать
code_item TYPE_CODE_ITEM 0x2001 неявный; необходимо проанализировать
string_data_item TYPE_STRING_DATA_ITEM 0x2002 неявное; необходимо выполнить синтаксический анализ
debug_info_item TYPE_DEBUG_INFO_ITEM 0x2003 неявное; необходимо выполнить синтаксический анализ
annotation_item TYPE_ANNOTATION_ITEM 0x2004 неявный; необходимо проанализировать
encoded_array_item TYPE_ENCODED_ARRAY_ITEM 0x2005 неявное; необходимо выполнить синтаксический анализ
annotations_directory_item TYPE_ANNOTATIONS_DIRECTORY_ITEM 0x2006 неявный; необходимо проанализировать
hiddenapi_class_data_item TYPE_HIDDENAPI_CLASS_DATA_ITEM 0xF000 неявный; необходимо проанализировать

string_id_item

Появляется в разделе string_ids

Выравнивание: 4 байта.

Название Формат Описание
string_data_off uint смещение от начала файла до строковых данных для этого элемента. Смещение должно указывать на место в разделе data, а данные должны быть в формате, указанном в разделе string_data_item ниже. Смещение не должно быть выровнено.

string_data_item

Появляется в разделе данных

Выравнивание: нет (побайтовое)

Название Формат Описание
utf16_size uleb128 размер этой строки в единицах кода UTF-16 (во многих системах это "длина строки"). То есть это декодированная длина строки. (Длина в кодированном виде определяется положением байта 0.)
данные ubyte[] последовательность кодовых единиц MUTF-8 (также известных как октеты или байты), за которой следует байт со значением 0. Подробную информацию о формате данных можно найти в разделе "Кодировка MUTF-8 (модифицированная UTF-8)" выше.

Примечание. Допускается использование строки, которая включает (в закодированном виде) суррогатные кодовые единицы UTF-16 (то есть U+d800 … U+dfff) по отдельности или в порядке, отличном от обычного кодирования Unicode в UTF-16. Если это необходимо, более высокие уровни использования строк должны отклонять такие недопустимые кодировки.

type_id_item

Появляется в разделе type_ids

Выравнивание: 4 байта.

Название Формат Описание
descriptor_idx uint индекс в списке string_ids для строки дескриптора этого типа. Строка должна соответствовать синтаксису TypeDescriptor, описанному выше.

proto_id_item

Указывается в разделе proto_ids.

Выравнивание: 4 байта.

Название Формат Описание
shorty_idx uint индекс в списке string_ids для строки краткого описания этого прототипа. Строка должна соответствовать синтаксису ShortyDescriptor, определенному выше, а также типу возвращаемого значения и параметрам этого элемента.
return_type_idx uint индекс в списке type_ids для типа возвращаемого значения этого прототипа
parameters_off uint смещение от начала файла до списка типов параметров для этого прототипа или 0, если у этого прототипа нет параметров. Если смещение не равно нулю, оно должно быть указано в разделе data, а данные в нем должны быть в формате, заданном параметром "type_list". Кроме того, в списке не должно быть ссылок на тип void.

field_id_item

Появляется в разделе field_ids

Выравнивание: 4 байта.

Название Формат Описание
class_idx ushort индекс в списке type_ids для определителя этого поля. Это должен быть тип класса, а не массив или примитивный тип.
type_idx ushort индекс в списке type_ids для типа этого поля
name_idx uint индекс в списке string_ids для названия этого поля. Строка должна соответствовать синтаксису MemberName, определенному выше.

method_id_item

Появляется в разделе method_ids.

Выравнивание: 4 байта.

Название Формат Описание
class_idx ushort индекс в списке type_ids для определителя этого метода. Это должен быть класс или массив, а не примитивный тип.
proto_idx ushort индекс в списке proto_ids для прототипа этого метода
name_idx uint индекс в списке string_ids для названия этого метода. Строка должна соответствовать синтаксису MemberName, описанному выше.

class_def_item

Появляется в разделе class_defs

Выравнивание: 4 байта

Название Формат Описание
class_idx uint индекс в списке type_ids для этого класса. Это должен быть тип класса, а не массив или примитивный тип.
access_flags uint флаги доступа для класса (public, final и т. д.). Подробную информацию можно найти в разделе access_flags.
superclass_idx uint Индекс в списке type_ids для надкласса или постоянное значение NO_INDEX, если у этого класса нет надкласса (то есть это корневой класс, например Object). Если этот элемент присутствует, он должен быть типом класса, а не массивом или примитивным типом.
interfaces_off uint смещение от начала файла до списка интерфейсов или 0, если интерфейсов нет. Это смещение должно быть указано в разделе data, а данные в нем должны быть в формате, заданном параметром type_list ниже. Каждый элемент списка должен быть типом класса (не массивом или примитивным типом), и не должно быть дубликатов.
source_file_idx uint индекс в списке string_ids для названия файла, содержащего исходный код (по крайней мере, большей части) этого класса, или специальное значение NO_INDEX, если такой информации нет. debug_info_item любого метода может переопределять этот исходный файл, но ожидается, что большинство классов будет поступать только из одного исходного файла.
annotations_off uint Смещение от начала файла до структуры аннотаций для этого класса или 0, если в этом классе нет аннотаций. Если смещение не равно нулю, оно должно быть указано в разделе data, а данные в нем должны быть представлены в формате, заданном параметром annotations_directory_item, описанным ниже. При этом все элементы должны ссылаться на этот класс как на определяющий.
class_data_off uint смещение от начала файла до связанных данных о курсе для этого объекта или 0, если для этого курса нет данных о курсе. (например, если этот класс является интерфейсом-маркером). Если смещение не равно нулю, оно должно быть указано в разделе data, а данные в нем должны быть в формате, заданном в разделе class_data_item ниже. Все элементы должны ссылаться на этот класс как на определяющий.
static_values_off uint Смещение от начала файла до списка начальных значений для полей static или 0, если таких полей нет (и все поля static должны быть инициализированы с помощью 0 или null). Это смещение должно быть указано в разделе data, а данные в нем должны быть в формате, заданном параметром encoded_array_item ниже. Размер массива не должен превышать количество полей static, объявленных этим классом, а элементы соответствуют полям static в том же порядке, в котором они объявлены в соответствующем field_list. Тип каждого элемента массива должен соответствовать объявленному типу соответствующего поля. Если в массиве меньше элементов, чем полей static, то оставшиеся поля инициализируются с соответствующим типу значением 0 или null.

call_site_id_item

Появляется в разделе call_site_ids

Выравнивание: 4 байта.

Название Формат Описание
call_site_off uint смещение от начала файла до определения сайта; Смещение должно находиться в разделе данных, а данные в нем должны быть в формате, указанном ниже в call_site_item.

call_site_item

Показывается в разделе данных

Выравнивание: нет (по байтам)

call_site_item – это encoded_array_item, элементы которого соответствуют аргументам, предоставленным методу загрузчика. Первые три аргумента:

  1. Дескриптор метода, представляющий метод начальной загрузки (VALUE_METHOD_HANDLE).
  2. Название метода, который должен разрешить загрузчик (VALUE_STRING).
  3. Тип метода, соответствующий типу имени метода, которое нужно разрешить (VALUE_METHOD_TYPE).

Дополнительные аргументы – это постоянные значения, передаваемые методу связывания начальной загрузки. Эти аргументы передаются в порядке их указания и без преобразования типов.

Дескриптор метода, представляющий метод начальной загрузки компоновщика, должен иметь тип возвращаемого значения java.lang.invoke.CallSite. Первые три типа параметров:

  1. java.lang.invoke.Lookup
  2. java.lang.String
  3. java.lang.invoke.MethodType

Типы параметров дополнительных аргументов определяются по их постоянным значениям.

method_handle_item

Появляется в разделе method_handles

Выравнивание: 4 байта.

Название Формат Описание
method_handle_type ushort тип дескриптора метода (см. таблицу ниже);
unused ushort (unused)
field_or_method_id ushort Идентификатор поля или метода в зависимости от того, является ли тип дескриптора метода методом доступа или вызывающим методом.
unused ushort (не используется)

Коды типов обработчиков методов

Константа Значение Описание
METHOD_HANDLE_TYPE_STATIC_PUT 0x00 Дескриптор метода является статическим сеттером поля (аксессором)
METHOD_HANDLE_TYPE_STATIC_GET 0x01 Дескриптор метода является статическим геттером поля (аксессором)
METHOD_HANDLE_TYPE_INSTANCE_PUT 0x02 Дескриптор метода является сеттером поля экземпляра (аксессором)
METHOD_HANDLE_TYPE_INSTANCE_GET 0x03 Дескриптор метода является геттером поля экземпляра (аксессором)
METHOD_HANDLE_TYPE_INVOKE_STATIC 0x04 Дескриптор метода – это статический вызывающий метод
METHOD_HANDLE_TYPE_INVOKE_INSTANCE 0x05 Дескриптор метода является вызывающим методом экземпляра
METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR 0x06 Дескриптор метода является вызывающим методом конструктора
METHOD_HANDLE_TYPE_INVOKE_DIRECT 0x07 Дескриптор метода – это прямой вызов метода.
METHOD_HANDLE_TYPE_INVOKE_INTERFACE 0x08 Дескриптор метода – это вызывающий метод интерфейса

class_data_item

Ссылка из class_def_item

Появляется в разделе данных

Выравнивание: нет (побайтовое)

Название Формат Описание
static_fields_size uleb128 количество статических полей, определенных в этом объекте;
instance_fields_size uleb128 количество полей экземпляра, определенных в этом элементе
direct_methods_size uleb128 количество прямых методов, определенных в этом элементе
virtual_methods_size uleb128 количество виртуальных методов, определенных в этом элементе;
static_fields encoded_field[static_fields_size] определенные статические поля, представленные в виде последовательности закодированных элементов. Поля должны быть отсортированы по столбцу field_idx в порядке возрастания.
instance_fields encoded_field[instance_fields_size] определенные поля экземпляра, представленные в виде последовательности закодированных элементов. Поля должны быть отсортированы по возрастанию значений field_idx.
direct_methods encoded_method[direct_methods_size] определенные прямые методы (static, private или конструктор), представленные в виде последовательности закодированных элементов. Способы оплаты должны быть отсортированы по возрастанию значения method_idx.
virtual_methods encoded_method[virtual_methods_size] определенные виртуальные методы (не static, private или конструктор), представленные в виде последовательности закодированных элементов. Этот список не должен включать унаследованные методы, если они не переопределены классом, который представляет этот элемент. Методы должны быть отсортированы по возрастанию значения переменной method_idx. method_idx виртуального метода не должно совпадать с прямого метода.

Примечание. Все элементы field_id и method_id должны ссылаться на один и тот же определяющий класс.

Формат encoded_field

Название Формат Описание
field_idx_diff uleb128 Индекс в списке field_ids для идентификатора этого поля (включает название и дескриптор), представленный как разница с индексом предыдущего элемента в списке. Индекс первого элемента в списке указывается напрямую.
access_flags uleb128 флаги доступа к полю (public, final и т. д.); Подробную информацию можно найти в разделе access_flags.

Формат encoded_method

Название Формат Описание
method_idx_diff uleb128 индекс в списке method_ids для идентификатора этого метода (включает название и дескриптор), представленный как разница с индексом предыдущего элемента в списке. Индекс первого элемента в списке указывается напрямую.
access_flags uleb128 флаги доступа для метода (public, final и т. д.). Подробную информацию можно найти в разделе access_flags.
код_выключения uleb128 смещение от начала файла до структуры кода для этого метода или 0, если этот метод является abstract или native. Смещение должно быть указано относительно местоположения в разделе data. Формат данных указан ниже в разделе "code_item".

type_list

Упоминается в class_def_item и proto_id_item

Появляется в разделе данных

Выравнивание: 4 байта

Название Формат Описание
размер uint размер списка в записях;
list type_item[size] элементы списка;

type_item format

Название Формат Описание
type_idx ushort индекс в списке type_ids;

code_item

Ссылка из encoded_method

Показывается в разделе данных

Выравнивание: 4 байта

Название Формат Описание
registers_size ushort количество регистров, используемых этим кодом;
ins_size ushort количество слов во входящих аргументах метода, для которого предназначен этот код;
outs_size ushort количество слов в пространстве исходящих аргументов, необходимых этому коду для вызова метода;
tries_size ushort количество try_item для этого экземпляра. Если значение не равно нулю, то эти значения будут представлены в виде массива tries сразу после insns.
debug_info_off uint Смещение от начала файла до последовательности сведений для отладки (номера строк + информация о локальных переменных) для этого кода или 0, если такой информации нет. Если смещение не равно нулю, оно должно указывать на местоположение в разделе data. Формат данных задается параметром "debug_info_item" ниже.
insns_size uint размер списка инструкций в 16-битных единицах кода;
insns ushort[insns_size] фактический массив байт-кода. Формат кода в массиве insns указан в сопутствующем документе Байт-код Dalvik. Обратите внимание, что, хотя это определено как массив ushort, некоторые внутренние структуры предпочитают выравнивание по четырем байтам. Кроме того, если это происходит в файле с перепутанным порядком байтов, то перестановка выполняется только для отдельных экземпляров ushort, а не для более крупных внутренних структур.
padding ushort (необязательно) = 0 два байта заполнения, чтобы выровнять tries по четырем байтам. Этот элемент присутствует, только если tries_size не равно нулю, а insns_size – нечетное число.
попытки "попробовать товар" [try_item] (необязательный) Массив, указывающий, где в коде перехватываются исключения и как их обрабатывать. Диапазоны элементов массива не должны пересекаться и должны быть упорядочены по возрастанию адресов. Этот элемент присутствует, только если значение tries_size не равно нулю.
Обработчики encoded_catch_handler_list (необязательный) байты, представляющие список списков типов перехвата и связанных адресов обработчиков. Каждый try_item имеет побайтовое смещение в этой структуре. Этот элемент присутствует, только если значение tries_size не равно нулю.

Формат try_item

Название Формат Описание
start_addr uint Начальный адрес блока кода, охваченного этой записью. Адрес – это количество 16-битных единиц кода до начала первой инструкции, которая должна быть покрыта.
insn_count ushort количество 16-битных единиц кода, охватываемых этой записью. Последняя единица кода – start_addr + insn_count - 1.
handler_off ushort смещение в байтах от начала связанного encoded_catch_hander_list до encoded_catch_handler для этой записи. Это должно быть смещение относительно начала encoded_catch_handler.

Формат encoded_catch_handler_list

Название Формат Описание
размер uleb128 размер списка в записях;
list encoded_catch_handler[handlers_size] фактический список списков обработчиков, представленный напрямую (не в виде смещений) и последовательно объединенный

Формат encoded_catch_handler

Название Формат Описание
размер sleb128 количество типов улова в этом списке. Если значение не положительное, то это отрицательное число типов catch, а за catch следует обработчик catch-all. Например, если size равен 0, это означает, что есть универсальный блок catch, но нет блоков catch с явным указанием типа. Значение size, равное 2, означает, что есть два явно типизированных блока catch и нет блока catch-all. А size со значением -1 означает, что есть один типизированный перехват и один перехват всех исключений.
Обработчики encoded_type_addr_pair[abs(size)] Поток закодированных элементов abs(size), по одному для каждого перехваченного типа, в порядке, в котором типы должны быть протестированы.
catch_all_addr uleb128 (необязательно) адрес обработчика для всех исключений в байт-коде. Этот элемент присутствует только в том случае, если значение size не положительное.

Формат encoded_type_addr_pair

Название Формат Описание
type_idx uleb128 индекс в списке type_ids для типа исключения, которое нужно перехватить.
addr uleb128 адрес обработчика исключений в байт-коде;

debug_info_item

Упоминается в code_item

Показывается в разделе данных

Выравнивание: нет (побайтовое)

Каждый элемент debug_info_item определяет конечный автомат с байт-кодом, вдохновленный форматом DWARF3. При интерпретации этого автомата создается таблица позиций и (потенциально) информация о локальных переменных для элемента code_item. Последовательность начинается с заголовка переменной длины (которая зависит от количества параметров метода), за которым следуют байт-коды конечного автомата, и заканчивается байтом DBG_END_SEQUENCE.

Конечный автомат состоит из пяти регистров. Регистр address представляет собой смещение инструкции в связанном insns_item в 16-битных единицах кода. Регистр address начинается с 0 в начале каждой последовательности debug_info и должен только монотонно возрастать. Регистр line представляет номер строки источника, который должен быть связан со следующей записью таблицы позиций, созданной конечным автоматом. Он инициализируется в заголовке последовательности и может меняться в положительном или отрицательном направлении, но никогда не должен быть меньше 1. Регистр source_file представляет исходный файл, на который ссылаются записи с номерами строк. Изначально ему присваивается значение source_file_idx из class_def_item. Две другие переменные, prologue_end и epilogue_begin, представляют собой логические флаги (инициализируются значением false), которые указывают, следует ли считать следующую позицию, полученную от устройства, прологом или эпилогом метода. Кроме того, конечный автомат должен отслеживать имя и тип последней локальной переменной, хранящейся в каждом регистре для кода DBG_RESTART_LOCAL.

Заголовок выглядит следующим образом:

Название Формат Описание
line_start uleb128 начальное значение регистра line конечного автомата; Не представляет собой фактическую запись о позиции.
parameters_size uleb128 количество закодированных названий параметров. Для каждого параметра метода, кроме параметра this метода экземпляра (если он есть), должно быть одно описание.
parameter_names uleb128p1[parameters_size] Индекс строки названия параметра метода. Закодированное значение NO_INDEX означает, что для связанного параметра нет названия. Дескриптор и сигнатура типа подразумеваются из дескриптора и сигнатуры метода.

Значения байт-кода:

Название Значение Формат Аргументы Описание
DBG_END_SEQUENCE 0x00 (нет) завершает последовательность сведений для отладки для code_item
DBG_ADVANCE_PC 0x01 uleb128 addr_diff addr_diff – сумма, которую нужно добавить в реестр адресов. перемещает указатель адреса без создания записи о позиции;
DBG_ADVANCE_LINE 0x02 sleb128 line_diff line_diff – значение, на которое нужно изменить регистр строки. перемещает указатель строки без создания записи о позиции;
DBG_START_LOCAL 0x03 uleb128 register_num
uleb128p1 name_idx
uleb128p1 type_idx
register_num – регистр, который будет содержать локальные
name_idx – строковый индекс имени
type_idx – индекс типа
вводит локальную переменную по текущему адресу. Если значение name_idx или type_idx неизвестно, то вместо него может быть указано NO_INDEX.
DBG_START_LOCAL_EXTENDED 0x04 uleb128 register_num
uleb128p1 name_idx
uleb128p1 type_idx
uleb128p1 sig_idx
register_num: регистр, который будет содержать local
name_idx: индекс строки имени
type_idx: индекс типа
sig_idx: индекс строки сигнатуры типа
представляет локальную переменную с сигнатурой типа по текущему адресу. Любой из параметров name_idx, type_idx или sig_idx может иметь значение NO_INDEX, если оно неизвестно. (Если sig_idx – это -1, то те же данные можно представить более эффективно, используя код операции DBG_START_LOCAL.)

Примечание. Ознакомьтесь с разделом dalvik.annotation.Signature ниже, чтобы узнать, как обрабатывать подписи.

DBG_END_LOCAL 0x05 uleb128 register_num register_num: зарегистрировать, что контент содержит местный контент Помечает текущую локальную переменную как находящуюся вне области видимости по текущему адресу.
DBG_RESTART_LOCAL 0x06 uleb128 register_num register_num: зарегистрируйтесь, чтобы перезапустить повторно вводит локальную переменную по текущему адресу. Название и тип совпадают с последними локальными данными, которые были активны в указанном реестре.
DBG_SET_PROLOGUE_END 0x07 (нет) Устанавливает регистр конечного автомата prologue_end, указывая, что следующая добавленная запись позиции должна считаться концом пролога метода (подходящее место для точки останова метода). Регистр prologue_end очищается любым специальным кодом операции (>= 0x0a).
DBG_SET_EPILOGUE_BEGIN 0x08 (none) Устанавливает регистр конечного автомата epilogue_begin, указывая, что следующая добавленная запись позиции должна считаться началом эпилога метода (подходящее место для приостановки выполнения перед выходом из метода). Регистр epilogue_begin очищается любым специальным операционным кодом (>= 0x0a).
DBG_SET_FILE 0x09 uleb128p1 name_idx name_idx – строковый индекс названия исходного файла; NO_INDEX, если неизвестно. указывает, что все последующие записи номеров строк относятся к этому названию исходного файла, а не к названию по умолчанию, указанному в code_item.
Специальные коды операций 0x0a…0xff (нет) увеличивает значения регистров line и address, создает запись о местоположении и очищает регистры prologue_end и epilogue_begin. Описание приведено ниже.

Специальные коды операций

Опкоды со значениями от 0x0a до 0xff (включительно) немного смещают регистры line и address, а затем создают новую запись в таблице позиций. Формулы для расчета прироста приведены ниже.

DBG_FIRST_SPECIAL = 0x0a  // the smallest special opcode
DBG_LINE_BASE   = -4      // the smallest line number increment
DBG_LINE_RANGE  = 15      // the number of line increments represented

adjusted_opcode = opcode - DBG_FIRST_SPECIAL

line += DBG_LINE_BASE + (adjusted_opcode % DBG_LINE_RANGE)
address += (adjusted_opcode / DBG_LINE_RANGE)

annotations_directory_item

Упоминается в class_def_item

Показывается в разделе данных

Выравнивание: 4 байта

Название Формат Описание
class_annotations_off uint Смещение от начала файла до аннотаций, сделанных непосредственно в классе, или 0, если в классе нет прямых аннотаций. Если смещение не равно нулю, оно должно указывать на местоположение в разделе data. Формат данных задается параметром "annotation_set_item" ниже.
fields_size uint количество полей, аннотированных этим объектом;
annotated_methods_size uint количество методов, аннотированных этим элементом
annotated_parameters_size uint количество списков параметров метода, аннотированных этим элементом;
field_annotations field_annotation[fields_size] (необязательный) список связанных аннотаций полей. Элементы списка должны быть отсортированы по возрастанию по полю field_idx.
method_annotations method_annotation[methods_size] (необязательный) список аннотаций связанных методов. Элементы списка должны быть отсортированы по возрастанию по полю method_idx.
parameter_annotations parameter_annotation[parameters_size] (необязательно) список аннотаций параметров метода. Элементы списка должны быть отсортированы по возрастанию по полю method_idx.

Примечание. Все экземпляры field_id и method_id элементов должны ссылаться на один и тот же определяющий класс.

Формат аннотации поля

Название Формат Описание
field_idx uint индекс в списке field_ids для идентификации поля, к которому относится аннотация.
annotations_off uint смещение от начала файла до списка аннотаций для поля. Смещение должно быть указано относительно местоположения в разделе data. Формат данных указан ниже в разделе "annotation_set_item".

Формат аннотации метода

Название Формат Описание
method_idx uint индекс в списке method_ids для идентификации аннотируемого метода.
annotations_off uint Смещение от начала файла до списка аннотаций для метода. Смещение должно указывать на место в разделе data. Формат данных определяется значением annotation_set_item.

Формат аннотации параметра

Название Формат Описание
method_idx uint индекс в списке method_ids для идентификации метода, параметры которого аннотируются.
annotations_off uint смещение от начала файла до списка аннотаций для параметров метода. Смещение должно быть указано относительно местоположения в разделе data. Формат данных указан ниже в разделе "annotation_set_ref_list".

annotation_set_ref_list

Ссылка из parameter_annotations_item

Появляется в разделе данных

Выравнивание: 4 байта

Название Формат Описание
размер uint размер списка в записях;
list annotation_set_ref_item[size] элементы списка

Формат annotation_set_ref_item

Название Формат Описание
annotations_off uint Смещение от начала файла до набора аннотаций, на который указывает ссылка, или 0, если у этого элемента нет аннотаций. Если смещение не равно нулю, оно должно указывать на местоположение в разделе data. Формат данных указан ниже в разделе "annotation_set_item".

annotation_set_item

Ссылка из annotations_directory_item, field_annotations_item, method_annotations_item и annotation_set_ref_item.

Показывается в разделе данных

Выравнивание: 4 байта

Название Формат Описание
размер uint размер набора в записях;
записи; annotation_off_item[size] элементы набора. Элементы должны быть отсортированы по возрастанию по значению type_idx.

Формат элемента annotation_off_item

Название Формат Описание
annotation_off uint смещение от начала файла до аннотации. Смещение должно указывать на место в разделе data, а формат данных в этом месте определяется значением annotation_item ниже.

annotation_item

Упоминается в annotation_set_item

Появляется в разделе данных

Выравнивание: нет (побайтовое)

Название Формат Описание
доступ ubyte видимость аннотации (см. ниже);
аннотация encoded_annotation закодированное содержимое аннотации в формате, описанном в разделе "encoded_annotation format" под заголовком "encoded_value encoding" выше.

Значения видимости

Ниже перечислены варианты для поля visibility в файле annotation_item:

Название Значение Описание
VISIBILITY_BUILD 0x00 предназначен для использования только во время сборки (например, при компиляции другого кода);
VISIBILITY_RUNTIME 0x01 предназначен для отображения во время выполнения.
VISIBILITY_SYSTEM 0x02 предназначен для того, чтобы быть видимым во время выполнения, но только для базовой системы (а не для обычного пользовательского кода);

encoded_array_item

Упоминается в class_def_item

Появляется в разделе данных

Выравнивание: нет (побайтовое)

Название Формат Описание
значение encoded_array байты, представляющие закодированное значение массива, в формате, указанном в разделе "encoded_array Format" под заголовком "encoded_value Encoding" выше.

hiddenapi_class_data_item

В этом разделе содержатся данные об ограниченных интерфейсах, используемых каждым классом.

Примечание. Функция скрытого API была добавлена в Android 10.0 и применяется только к DEX-файлам классов в пути загрузки. Список флагов, описанных ниже, может быть расширен в будущих версиях Android. Подробнее об ограничениях на использование интерфейсов, не относящихся к SDK…

Название Формат Описание
размер uint общий размер раздела
компенсации uint[] Массив смещений, индексированных по class_idx. Нулевая запись массива с индексом class_idx означает, что либо для этого class_idx нет данных, либо все флаги скрытого API равны нулю. В противном случае запись массива не равна нулю и содержит смещение от начала раздела до массива скрытых флагов API для этого class_idx.
флаги uleb128[] объединенные массивы скрытых флагов API для каждого класса. Возможные значения флагов описаны в таблице ниже. Флаги кодируются в том же порядке, что и поля и методы в данных класса.

Типы пометок об ограничениях:

Название Значение Описание
белый список 0 Интерфейсы, которые можно свободно использовать и которые поддерживаются в рамках официально задокументированного индекса пакетов фреймворка Android.
серый список 1 Интерфейсы, не относящиеся к SDK, которые можно использовать независимо от целевого уровня API приложения.
черный список 2 Интерфейсы, не относящиеся к SDK, которые нельзя использовать независимо от целевого уровня API приложения. Попытка получить доступ к одному из этих интерфейсов приведет к ошибке выполнения.
greylist‑max‑o 3 Интерфейсы не из SDK, которые можно использовать в Android 8.x и более ранних версий, если они не ограничены.
greylist‑max‑p 4 Интерфейсы не из SDK, которые можно использовать в Android 9.x, если они не ограничены.
greylist‑max‑q 5 Интерфейсы, не относящиеся к SDK, которые можно использовать для Android 10.x, если они не ограничены.
greylist‑max‑r 6 Интерфейсы, не относящиеся к SDK, которые можно использовать в Android 11.x, если они не ограничены.

Системные аннотации

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

Системные аннотации представлены в файлах .dex как аннотации с параметром видимости VISIBILITY_SYSTEM.

dalvik.annotation.AnnotationDefault

Появляется в интерфейсах аннотаций.

Аннотация AnnotationDefault прикрепляется к каждому интерфейсу аннотаций, в котором нужно указать привязки по умолчанию.

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

dalvik.annotation.EnclosingClass

Показывается в курсах

Аннотация EnclosingClass прикрепляется к каждому классу, который либо определен как член другого класса, либо является анонимным, но не определен в теле метода (например, синтетический внутренний класс). У каждого класса с этой аннотацией должна быть аннотация InnerClass. Кроме того, в классе не должно быть одновременно аннотаций EnclosingClass и EnclosingMethod.

Название Формат Описание
значение Класс класс, который наиболее точно определяет лексическую область видимости этого класса

dalvik.annotation.EnclosingMethod

Показывается в курсах

Аннотация EnclosingMethod прикрепляется к каждому классу, определенному в теле метода. Каждый класс с этой аннотацией также должен иметь аннотацию InnerClass. Кроме того, у класса не может быть одновременно аннотаций EnclosingClass и EnclosingMethod.

Название Формат Описание
значение Метод метод, который наиболее точно определяет лексическую область действия этого класса;

dalvik.annotation.InnerClass

Показывается в курсах

Аннотация InnerClass прикрепляется к каждому классу, который определен в лексической области видимости определения другого класса. Если в классе есть эта аннотация, то в нем также должна быть аннотация EnclosingClass или EnclosingMethod.

Название Формат Описание
название Строка Простое имя этого класса, объявленное изначально (без префикса пакета). Если класс анонимный, то название – null.
accessFlags ПРХВ первоначально объявленные флаги доступа класса (которые могут отличаться от действующих флагов из-за несоответствия между моделями выполнения исходного языка и целевой виртуальной машины);

dalvik.annotation.MemberClasses

Показывается в курсах

К каждому классу, объявляющему классы-участники, прикреплена аннотация MemberClasses. (Внутренний класс является прямым, если у него есть имя.)

Название Формат Описание
значение Class[] массив классов участников;

dalvik.annotation.MethodParameters

Появляется в методах

Примечание. Эта аннотация была добавлена после Android 7.1. На устройствах с более ранними версиями Android он будет игнорироваться.

Аннотация MethodParameters необязательна и может использоваться для предоставления метаданных параметров, таких как имена параметров и модификаторы.

Аннотацию можно опустить в методе или конструкторе, если метаданные параметра не требуются во время выполнения. java.lang.reflect.Parameter.isNamePresent() можно использовать, чтобы проверить, есть ли метаданные для параметра, а связанные методы отражения, такие как java.lang.reflect.Parameter.getName(), будут возвращаться к режиму работы по умолчанию во время выполнения, если информация отсутствует.

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

Аннотация MethodParameters описывает только отдельные параметры метода. Поэтому компиляторы могут полностью опускать аннотацию для конструкторов и методов, у которых нет параметров, чтобы уменьшить размер кода и повысить эффективность во время выполнения.

Размеры массивов, описанных ниже, должны совпадать с размерами структуры method_id_item dex, связанной с методом. В противном случае во время выполнения будет выброшено исключение java.lang.reflect.MalformedParametersException.

То есть method_id_item.proto_idx -> proto_id_item.parameters_off -> type_list.size должны быть такими же, как names().length и accessFlags().length.

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

Название Формат Описание
имена String[] Названия формальных параметров для связанного метода. Массив не должен быть пустым, если формальные параметры отсутствуют. Если у формального параметра с определенным индексом нет имени, значение в массиве должно быть нулевым.
Если строки с названиями параметров пустые или содержат символы ".", ";", "[" или "/", во время выполнения будет сгенерирована ошибка java.lang.reflect.MalformedParametersException.
accessFlags int[] Флаги доступа формальных параметров для связанного метода. Массив не должен быть пустым, если формальные параметры отсутствуют.
Значение представляет собой битовую маску со следующими значениями:
  • 0x0010 : final, параметр объявлен как final;
  • 0x1000 – синтетический параметр, добавленный компилятором.
  • 0x8000 – обязательный параметр, который является синтетическим, но также подразумевается спецификацией языка.
Если какие-либо биты установлены за пределами этого набора, во время выполнения будет выдано исключение java.lang.reflect.MalformedParametersException.

dalvik.annotation.Signature

Появляется в классах, полях и методах

Аннотация Signature прикрепляется к каждому классу, полю или методу, которые определяются с помощью более сложного типа, чем тот, который можно представить с помощью type_id_item. Формат .dex не определяет формат подписей. Он лишь позволяет представлять подписи, необходимые для успешной реализации семантики исходного языка. Поэтому реализации виртуальных машин обычно не анализируют и не проверяют подписи. Подписи просто передаются API и инструментам более высокого уровня (например, отладчикам). Поэтому при использовании подписи следует учитывать, что она может быть недействительной, и предусмотреть возможность обработки синтаксически неверной подписи.

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

Название Формат Описание
значение String[] Сигнатура этого класса или элемента в виде массива строк, которые нужно объединить.

dalvik.annotation.Throws

Появляется в методах

Аннотация Throws прикрепляется к каждому методу, который объявлен как выбрасывающий один или несколько типов исключений.

Название Формат Описание
значение Class[] массив типов исключений, которые были вызваны;