Format wykonywalny Dalvik

Ten dokument opisuje układ i zawartość plików .dex, które służą do przechowywania zestawu definicji klas i powiązanych z nimi danych pomocniczych.

Przewodnik po typach

Nazwa Opis
bajt 8-bitowa liczba całkowita ze znakiem
ubyte 8-bitowa liczba bez znaku typu int
krótki 16-bitowa liczba całkowita ze znakiem w systemie little-endian
ushort 16-bitowa bez znaku int, małe endian
int 32-bitowa liczba całkowita ze znakiem, małe endian
uint 32-bitowa bez znaku int, małe endian
długi 64-bitowa liczba całkowita ze znakiem, małe endian
ulong 64-bitowa bezznakowa int, little-endian
sleb128 podpisany LEB128 o zmiennej długości (patrz poniżej)
uleb128 bez znaku LEB128 o zmiennej długości (patrz poniżej)
uleb128p1 bez znaku LEB128 plus 1 o zmiennej długości (patrz poniżej)

LEB128

LEB128 („Little-Endian Base 128”) to kodowanie o zmiennej długości dla dowolnych wartości całkowitych ze znakiem lub bez znaku. Format został zapożyczony ze specyfikacji DWARF3. W pliku .dex kod LEB128 jest używany tylko do kodowania wartości 32-bitowych.

Każda wartość zakodowana w formacie LEB128 składa się z 1–5 bajtów, które razem stanowią pojedynczą 32-bitową wartość. Każdy bajt ma ustawiony najbardziej znaczący bit, z wyjątkiem ostatniego bajtu w sekwencji, którego najbardziej znaczący bit jest pusty. Pozostałe 7 bitów każdego bajta to ładunek użyteczny, przy czym 7 najmniej istotnych bitów wartości w pierwszym bajcie, 7 następnych w drugim itd. W przypadku podpisanego LEB128 (sleb128) najbardziej znaczący bit danych w ostatnim bajcie sekwencji jest rozszerzany o znak, aby uzyskać ostateczną wartość. W przypadku liczb bez znaku (uleb128) wszystkie bity, które nie są wyraźnie reprezentowane, są interpretowane jako 0.

Diagram bitowy dwubajtowej wartości LEB128
Pierwszy bajt Drugi bajt
1 bitów6 bitów5 bitów4 bit3 bit2 bit1 bitów0 0 bit13 bitów12 bitów11 bit10 bitów9 bitów8 bitów7

Wariant uleb128p1 służy do reprezentowania wartości ze znakiem, gdzie reprezentacja ma wartość plus 1 zakodowana jako uleb128. Dzięki temu kodowanie wartości -1 (czyli nieoznaczonej wartości 0xffffffff) – ale nie innych wartości ujemnych – zajmuje 1 bajt. Jest to przydatne w tych przypadkach, gdy reprezentowana liczba musi być nieujemna lub równa -1 (lub 0xffffffff), a nie są dozwolone inne wartości ujemne (lub gdy duże wartości bez znaku są mało prawdopodobne).

Oto kilka przykładów formatów:

Sekwencja zakodowana sleb128 uleb128 uleb128p1
0000-1
01110
7f-1127126
80 7f-1281625616255

Układ pliku

Nazwa Format Opis
nagłówek header_item nagłówek
string_ids string_id_item[] lista identyfikatorów ciągu znaków. Są to identyfikatory wszystkich ciągów znaków używanych przez ten plik, albo do wewnętrznego nazewnictwa (np. opisy typów), albo jako obiekty statyczne odwołujące się do kodu. Lista musi być posortowana według zawartości ciągu znaków za pomocą wartości punktów kodu UTF-16 (nie w sposób zależny od lokalizacji) i nie może zawierać zduplikowanych wpisów.
type_ids type_id_item[] typów identyfikatorów. Są to identyfikatory wszystkich typów (klas, tablic lub typów prymitywnych), do których odwołuje się ten plik, niezależnie od tego, czy są zdefiniowane w pliku. Lista musi być posortowana według indeksu string_idi nie może zawierać zduplikowanych wpisów.
proto_ids proto_id_item[] listę identyfikatorów prototypu metody. To są identyfikatory wszystkich prototypów, do których odnosi się ten plik. Lista ta musi być posortowana według typu zwracanego (według indeksu type_id), a następnie według listy argumentów (kolejność leksykograficzna, poszczególne argumenty posortowane według indeksu type_id). Lista nie może zawierać zduplikowanych pozycji.
field_ids field_id_item[] lista identyfikatorów pól. Są to identyfikatory wszystkich pól, do których odwołuje się ten plik, niezależnie od tego, czy są one w nim zdefiniowane. Ta lista musi być posortowana, przy czym definiujący typ (według indeksu type_id) jest głównym elementem, nazwa pola (według indeksu string_id) jest elementem pośrednim, a typ (według indeksu type_id) jest elementem podrzędnym. Lista nie może zawierać zduplikowanych pozycji.
method_ids method_id_item[] lista identyfikatorów metody. Są to identyfikatory wszystkich metod, do których odwołuje się ten plik, niezależnie od tego, czy są zdefiniowane w pliku. Ta lista musi być posortowana, przy czym typ definiujący (według indeksu type_id) ma najwyższy priorytet, nazwa metody (według indeksu string_id) ma priorytet pośredni, a prototyp metody (według indeksu proto_id) ma najniższy priorytet. Lista nie może zawierać zduplikowanych pozycji.
class_defs class_def_item[] lista definicji klas. Klasy muszą być uporządkowane w taki sposób, aby superklasa danej klasy i zaimplementowane interfejsy były na liście wcześniej niż klasa referencyjna. Ponadto definicja klasy o tej samej nazwie nie może występować więcej niż raz na liście.
call_site_ids call_site_id_item[] lista identyfikatorów witryn wywołania. Są to identyfikatory wszystkich miejsc wywołania, do których odwołuje się ten plik, niezależnie od tego, czy są w nim zdefiniowane. Ta lista musi być posortowana w kolejności rosnącej według kolumny call_site_off.
method_handles method_handle_item[] metody. Lista wszystkich uchwytów metody używanych przez ten plik, niezależnie od tego, czy są zdefiniowane w pliku. Ta lista nie jest posortowana i może zawierać zduplikowane pozycje, które logicznie odpowiadają różnym instancjom uchwytu metody.
dane ubyte[] obszar danych zawierający wszystkie dane pomocnicze dotyczące wymienionych powyżej tabel. Różne elementy mają różne wymagania dotyczące wyrównania. W razie potrzeby przed każdym elementem wstawiane są bajty wypełnienia, aby zapewnić prawidłowe wyrównanie.
link_data ubyte[] dane używane w plikach połączonych statycznie. Format danych w tej sekcji nie jest określony w tym dokumencie. Ta sekcja jest pusta w niepołączonych plikach, a implementacje w czasie wykonywania mogą jej używać według uznania.

Format kontenera

Wersja 41 wprowadza nowy format kontenera danych DEX, który ma na celu oszczędzanie miejsca. Ten format kontenera umożliwia połączenie kilku logicznych plików DEX w jeden fizyczny plik. Nowy format to głównie proste złączenie plików w poprzednim formacie, z kilkoma różnicami:

  • file_size to rozmiar pliku logicznego, a nie fizycznego. Można go użyć do iteracji po wszystkich plikach logicznych w kontenerze.
  • Logiczne pliki dex mogą odwoływać się do dowolnych późniejszych danych w kontenerze (ale nie wcześniejszych). Dzięki temu pliki dex mogą udostępniać sobie dane, np. ciągi znaków.
  • Wszystkie przesunięcia są względne względem fizycznego pliku. Brak przesunięcia względem nagłówka. Dzięki temu sekcje z przesunięciem mogą być udostępniane między plikami logicznymi.
  • Nagłówek dodaje 2 nowe pola opisujące granice kontenera. Jest to dodatkowa kontrola spójności, która ułatwia przenoszenie kodu do nowego formatu.
  • Funkcje data_size i data_off nie są już używane. Dane mogą być rozproszone w wielu plikach logicznych i nie muszą być ciągłe.

Definicje pól bitowych, ciągów tekstowych i stałych

DEX_FILE_MAGIC

Umieszczony w header_item

Stałe tablice/ciągi znaków DEX_FILE_MAGIC to lista bajtów, która musi znajdować się na początku pliku .dex, aby był on rozpoznawany jako taki. Wartość celowo zawiera znak końca wiersza ("\n" lub 0x0a) oraz bajt null ("\0" lub 0x00), aby ułatwić wykrywanie pewnych form uszkodzenia. Wartość ta koduje również numer wersji formatu jako 3 cyfry dziesiętne, które powinny rosnąć monotonicznie wraz z rozwojem formatu.

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

Uwaga: w wersji 10.0 systemu Android dodano obsługę wersji 040 formatu, która rozszerzyła zestaw dozwolonych znaków w SimpleNames.

Uwaga: obsługa wersji 039 tego formatu została dodana w wersji Androida 9.0, która wprowadziła 2 nowe bajtkody: const-method-handleconst-method-type. (są one opisane w tabeli Podsumowanie zestawu kodu bajtowego). W Androidzie 10 w wersji 039 format pliku DEX został rozszerzony o ukryte informacje API, które dotyczą tylko plików DEX na ścieżce klasy uruchamiania.

Uwaga: w wersji 8.0 Androida dodano obsługę wersji 038 tego formatu. W wersji 038 dodano nowe bajtkody (invoke-polymorphicinvoke-custom) oraz dane dotyczące uchwytów metod.

Uwaga: obsługa wersji 037 tego formatu została dodana w wersji 7.0 Androida. Przed wersją 037 większość wersji Androida używała wersji 035 tego formatu. Jedyną różnicą między wersjami 035037 jest dodanie domyślnych metod i dostosowanie invoke.

Uwaga: co najmniej kilka wcześniejszych wersji tego formatu było używanych w publicznych wersjach oprogramowania dostępnych dla szerokiego grona użytkowników. Na przykład wersja 009 była używana w przypadku wersji M3 platformy Android (listopad–grudzień 2007 r.), a wersja 013 – w przypadku wersji M5 tej platformy (luty–marzec 2008 r.). W kilku aspektach te wcześniejsze wersje formatu różnią się znacznie od wersji opisanej w tym dokumencie.

ENDIAN_CONSTANT i REVERSE_ENDIAN_CONSTANT

Umieszczony w header_item

Stała ENDIAN_CONSTANT służy do wskazywania kodowania bajtów pliku, w którym się znajduje. Chociaż standardowy format .dex jest little-endian, implementacje mogą przeprowadzić zamianę bajtów. Jeśli implementacja napotka nagłówek, którego endian_tag to REVERSE_ENDIAN_CONSTANTzamiast ENDIAN_CONSTANT, będzie wiedzieć, że bajty w pliku zostały zamienione w nieoczekiwanej formie.

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

NO_INDEX

Umieszczone w elementach class_def_item i debug_info_item

Wartość stała NO_INDEX wskazuje, że wartość indeksu jest nieobecna.

Uwaga: ta wartość nie jest zdefiniowana jako 0, ponieważ jest to zwykle prawidłowy indeks.

Wybrana wartość NO_INDEX może być reprezentowana jako pojedynczy bajt w kodowaniu uleb128p1.

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

definicje access_flags

Umieszczone w elementach class_def_item, encoded_field, encoded_method i InnerClass.

Pola bitowe tych flag służą do wskazywania właściwości ułatwień dostępu i ogólnych właściwości klas i elementów klasy.

Nazwa Wartość Zajęcia (i adnotacje InnerClass) Pola Metody
ACC_PUBLIC 0x1 public: widoczne wszędzie public: widoczne wszędzie public: widoczne wszędzie
ACC_PRIVATE 0x2 * private: widoczne tylko dla klasy definiującej private: widoczne tylko dla klasy definiującej private: widoczne tylko dla klasy definiującej
ACC_PROTECTED 0x4 * protected: widoczne dla pakietu i podklas protected: widoczne dla pakietu i podklas, protected: widoczne dla pakietu i podklas,
ACC_STATIC 0x8 * static: nie jest konstruowany z poziomu zewnętrznym this odniesienie static: globalny do zdefiniowania klasy static: nie przyjmuje argumentu this
ACC_FINAL 0x10 final: nie można utworzyć podklasy final: nie można zmienić po utworzeniu final: nie można zastąpić
ACC_SYNCHRONIZED 0x20     synchronized: powiązany blokada jest automatycznie nabywany w okresie wywołania tej metody.

Uwaga: to ustawienie jest prawidłowe tylko wtedy, gdy ACC_NATIVE jest również ustawione.

ACC_VOLATILE 0x40   volatile: specjalne reguły dostępu ułatwiające bezpieczne prowadzenie wątku  
ACC_BRIDGE 0x40     metoda mostu, dodana automatycznie przez kompilator jako bezpieczna pod względem typów;
ACC_TRANSIENT 0x80   transient: nie należy zapisywać za pomocą domyślnej serializacji  
ACC_VARARGS 0x80     ostatni argument powinien być traktowany przez kompilator jako argument „reszta”
ACC_NATIVE 0 x 100     native: zaimplementowany w kodzie natywnym
ACC_INTERFACE 0 x 200 interface: abstrakcyjna klasa z wieloma implementacjami    
ACC_ABSTRACT 0x400 abstract: nie można utworzyć bezpośrednio   abstract: nie jest obsługiwane przez tę klasę
ACC_STRICT 0x800     strictfp: ścisłe reguły dotyczące obliczeń zmiennoprzecinkowych
ACC_SYNTHETIC 0x1000 nie są bezpośrednio zdefiniowane w kodzie źródłowym; nie są bezpośrednio zdefiniowane w kodzie źródłowym; nie są bezpośrednio zdefiniowane w kodzie źródłowym;
ACC_ANNOTATION 0x2000 zadeklarowana jako klasa adnotacji,    
ACC_ENUM 0x4000 zadeklarowany jako typ wyliczeniowy. zadeklarowana jako wartość wyliczeniowa  
(nieużywany) 0x8000      
ACC_CONSTRUCTOR 0x10000     metoda konstruktora (inicjator klasy lub wystąpienia);
ACC_DECLARED_
SYNCHRONIZED
0x20000     Zadeklarowano synchronized.

Uwaga: nie ma to wpływu na wykonanie (poza odzwierciedleniem tej flagi).

* Dozwolone tylko w przypadku adnotacji InnerClass. Nie można ich używać w przypadku adnotacji class_def_item.

Zmodyfikowane kodowanie UTF-8

W ramach ułatwienia obsługi starszych wersji format .dex koduje dane ciągu znaków w formie de facto standardowej zmodyfikowanej wersji UTF-8, zwanej dalej MUTF-8. Ten format jest identyczny ze standardowym UTF-8, z tym wyjątkiem, że:

  • Używane są tylko kodowania jedno-, dwu- i trzybajtowe.
  • Punkty kodu z zakresu U+10000U+10ffff są kodowane jako para zastępcza, z której każda jest reprezentowana jako 3-bajtowa wartość zakodowana.
  • Punkt kodu U+0000 jest kodowany w postaci 2-bajtowej.
  • Prosty bajt null (wartość 0) wskazuje koniec ciągu, zgodnie ze standardową interpretacją w języku C.

Pierwsze 2 punkty można podsumować w ten sposób: MUTF-8 to kodowanie UTF-16, a nie bezpośredni format kodowania znaków Unicode.

Ostatnie 2 elementy umożliwiają jednoczesne uwzględnienie punktu kodu U+0000 w ciągu znaków i dalsze manipulowanie nim jako ciągiem znaków zakończonym zerem w stylu C.

Jednak specjalne kodowanie U+0000 oznacza, że w przeciwieństwie do normalnego UTF-8 wynik wywołania standardowej funkcji C strcmp() na parze ciągów tekstowych MUTF-8 nie zawsze wskazuje prawidłowo podpisany wynik porównania ciągów nierównych. Jeśli istotne jest sortowanie (a nie tylko sprawdzanie równości), najprostszym sposobem porównywania ciągów znaków MUTF-8 jest ich dekodowanie znak po znaku i porównywanie uzyskanych wartości. Możliwe są też bardziej zaawansowane implementacje.

Więcej informacji o kodowaniu znaków znajdziesz w standardzie Unicode. Kodowanie MUTF-8 jest w większym stopniu podobne do (relatywnie mniej znanego) kodowania CESU-8 niż do UTF-8.

encoded_value kodowanie

Umieszczone w elementach annotation_element i encoded_array_item

encoded_value to zakodowany element (prawie) dowolnych danych uporządkowanych hierarchicznie. Kodowanie ma być zwięzłe i łatwe do zanalizowania.

Nazwa Format Opis
(value_arg << 5) | value_type ubyte bajt określający typ bezpośrednio następnego value z opcjonalnym argumentem wyjaśniającym w 3 najstarszych bitach. Poniżej znajdziesz różne definicje value. W większości przypadków value_arg koduje długość bezpośrednio następnego value w bajtach, jako (size - 1), np. 0 oznacza, że wartość wymaga 1 bajta, a 7 – 8 bajtów. Istnieją jednak wyjątki, o których mowa poniżej.
wartość ubyte[] bajty reprezentujące wartość, o zmiennej długości i interpretowane w zależności od różnych bajtów value_type, ale zawsze w systemie little-endian. Poniżej znajdziesz definicje poszczególnych wartości.

Formaty wartości

Wpisz nazwę value_type value_arg Format value Format Opis
VALUE_BYTE 0x00 (brak; musi być 0) ubyte[1] o wartości całkowitej ze znakiem w 1 bajcie.
VALUE_SHORT 0x02 rozmiar - 1 (0…1) ubyte[size] dwubajtowa liczba całkowita ze znakiem, rozszerzona o znak;
VALUE_CHAR 0x03 rozmiar - 1 (0…1) ubyte[size] bez znaku, 2-bajtowa wartość liczby całkowitej, rozszerzona do pełnego rozmiaru za pomocą zera
VALUE_INT 0x04 size - 1 (0…3) ubyte[size] 4-bajtowa liczba całkowita ze znakiem, z rozszerzonym znakiem.
VALUE_LONG 0x06 size - 1 (0…7) ubyte[size] ośmiobajtowa liczba całkowita ze znakiem, z rozszerzeniem znaku;
VALUE_FLOAT 0x10 size - 1 (0…3) ubyte[size] czterobajtowy wzór bitów rozszerzony zera w prawo i interpretowany jako 32-bitowa wartość zmiennoprzecinkowa IEEE754
VALUE_DOUBLE 0x11 size - 1 (0…7) ubyte[size] ośmiobajtowy wzór bitów rozszerzony o zera w prawo i interpretowany jako 64-bitowa wartość zmiennoprzecinkowa IEEE754.
VALUE_METHOD_TYPE 0 x 15 size - 1 (0…3) ubyte[size] bez znaku (rozszerzona o 0) wartość całkowita o cztery bajty, interpretowana jako indeks w sekcji proto_ids i reprezentująca wartość typu metody
VALUE_METHOD_HANDLE 0x16 size - 1 (0…3) ubyte[size] bez znaku (rozszerzony o 0) wartość całkowita o cztery bajty, interpretowana jako indeks w sekcji method_handles i reprezentująca wartość uchwytu metody
VALUE_STRING 0x17 size - 1 (0…3) ubyte[size] bez znaku (rozszerzona o 0) wartość liczby całkowitej o cztery bajty, interpretowana jako indeks w sekcji string_ids i reprezentująca wartość ciągu znaków
VALUE_TYPE 0 x 18 size - 1 (0…3) ubyte[size] bez znaku (rozszerzony o zerowanie) wartość całkowita o cztery bajty, interpretowana jako indeks w sekcji type_ids i reprezentująca wartość typu/klasy odbicienia
VALUE_FIELD 0x19 size - 1 (0…3) ubyte[size] bez znaku (rozszerzony o zerowanie) wartość całkowita o cztery bajty, interpretowana jako indeks w sekcji field_ids i przedstawiająca wartość pola odzwierciedlonego
VALUE_METHOD 0x1a size - 1 (0…3) ubyte[size] bez znaku (rozszerzony o zerowanie) wartość całkowita o cztery bajty, interpretowana jako indeks w sekcji method_ids i przedstawiająca wartość metody odzwierciedlającej
VALUE_ENUM 0x1b size - 1 (0…3) ubyte[size] bez znaku (rozszerzona o zerowanie) wartość całkowita o cztery bajty, interpretowana jako indeks w sekcji field_ids i przedstawiająca wartość stałej typu wyliczonego
VALUE_ARRAY 0x1c (brak; musi być 0) encoded_array tablica wartości w formacie określonym przez „format encoded_array” poniżej. Rozmiar value jest domyślnie określony w kodzie.
VALUE_ANNOTATION 0x1d (brak; musi być 0) encoded_annotation adnotację podrzędną w formacie określonym przez „format encoded_annotation” poniżej. Rozmiar value jest domyślnie uwzględniony w kodowaniu.
VALUE_NULL 0x1e (brak; musi być 0) (brak) null wartość referencyjna
VALUE_BOOLEAN 0x1f wartość logiczna (0…1) (brak) wartość jednobitowa: 0 dla false1 dla true. Bit jest reprezentowany w value_arg.

Format encoded_array

Nazwa Format Opis
rozmiar uleb128 liczba elementów w tablicy
wartości encoded_value[size] sekwencja size encoded_value bajtów w formacie określonym w tej sekcji, połączonych sekwencyjnie.

Format encoded_annotation

Nazwa Format Opis
type_idx uleb128 typ adnotacji. Musi to być typ klasy (a nie tablicy ani typu prymitywnego).
rozmiar uleb128 Liczba mapowań nazwa-wartość w tej adnotacji
elementów annotation_element[size] elementy adnotacji, reprezentowane bezpośrednio w wierszu (nie jako przesunięcia). Elementy muszą być posortowane w kolejności rosnącej według indeksu string_id.

Format annotation_element

Nazwa Format Opis
name_idx uleb128 nazwa elementu, która jest indeksem w sekcji string_ids. Ciąg musi być zgodny ze składnią NazwaCzłonka zdefiniowaną powyżej.
wartość encoded_value wartość elementu

Składnia ciągu znaków

W pliku .dex występuje kilka rodzajów elementów, które ostatecznie odwołują się do ciągu znaków. Definicje w stylu BNF wskazują dopuszczalną składnię tych ciągów znaków.

SimpleName

SimpleName jest podstawą składni nazw innych rzeczy. Format .dex daje dużą swobodę (znacznie większą niż w przypadku większości języków źródłowych). Krótko mówiąc, prosta nazwa składa się z dowolnego znaku alfabetycznego lub cyfry z dolnego zakresu ASCII, kilku określonych symboli z dolnego zakresu ASCII oraz większości punktów kodu spoza ASCII, które nie są znakami kontrolnymi, spacją ani znakami specjalnymi. Od wersji 040 format ten umożliwia również stosowanie znaków spacji (kategoria znaków Unicode Zs). Pamiętaj, że punkty kodu zastępczego (w zakresie U+d800U+dfff) nie są uznawane za prawidłowe znaki nazwy, ale dodatkowe znaki Unicode prawidłowe (co jest reprezentowane przez ostatnią alternatywę reguły SimpleNameChar), i powinny być reprezentowane w pliku jako pary punktów kodu zastępczego w koderze MUTF-8.

SimpleName →
SimpleNameChar (SimpleNameChar)*
SimpleNameChar
'A''Z'
| 'a''z'
| '0''9'
| ' ' od wersji DEX 040
| '$'
| '-'
| '_'
| U+00a0 od wersji DEX 040
| U+00a1U+1fff
| U+2000U+200a od wersji DEX 040
| U+2010U+2027
| U+202f od wersji DEX 040
| U+2030U+d7ff
| U+e000U+ffef
| U+10000U+10ffff

MemberName

używany przez field_id_item i method_id_item

NazwaCzłonka to nazwa elementu klasy, którym mogą być pola, metody i klasy wewnętrzne.

NazwaCzłonka →
SimpleName
| '<' SimpleName '>'

FullClassName

Pełna nazwa klasy to pełna nazwa klasy, w tym opcjonalny specyfikator pakietu, po którym następuje wymagana nazwa.

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

TypeDescriptor

Używany przez type_id_item

TypeDescriptor to reprezentacja dowolnego typu, w tym typów prymitywnych, klas, tablic i void. Poniżej znajdziesz wyjaśnienie różnych wersji.

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

ShortyDescriptor

Używany przez proto_id_item

ShortyDescriptor to krótka reprezentacja prototypu metody, w tym typów zwracanych wartości i parametrów, z tym że nie ma rozróżnienia między różnymi typami referencji (klasy lub tablicy). Zamiast tego wszystkie typy odwołań są reprezentowane przez pojedynczy znak 'L'.

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

Semantyka typu opisu

Oto znaczenie każdej z wariantów TypeDescriptor.

Składnia Znaczenie
V void; dotyczy tylko typów zwrotów
Z boolean
B byte
S short
C char
I int
J long
F float
D double
Lpełna/kwalifikowana nazwa; zajęcia fully.qualified.Name
[descriptor tablica descriptor, która może być używana rekurencyjnie w przypadku tablic tablic, ale nie może mieć więcej niż 255 wymiarów.

Elementy i powiązane struktury

Ta sekcja zawiera definicje wszystkich elementów najwyższego poziomu, które mogą występować w pliku .dex.

header_item

Wyświetla się w sekcji nagłówka

Wyrównanie: 4 bajty

Nazwa Format Opis
magia ubyte[8] = DEX_FILE_MAGIC magic value. Więcej informacji znajdziesz w sekcji „DEX_FILE_MAGIC” powyżej.
suma kontrolna uint suma kontrolna adler32 reszty pliku (wszystko oprócz magic i tego pola); służy do wykrywania uszkodzeń pliku
podpis ubyte[20] podpis SHA-1 (skrót) reszty pliku (wszystko oprócz magic, checksum i tego pola); służy do jednoznacznej identyfikacji plików
file_size uint

rozmiar całego pliku (w tym nagłówka) w bajtach (w wersji 40 lub wcześniejszej)

odległość w bajtach od początku tego nagłówka do następnego nagłówka lub do końca całego pliku (kontenera). (w wersji 41 lub nowszej)

header_size uint

rozmiar nagłówka (całej tej sekcji) w bajtach. Dzięki temu można uzyskać co najmniej ograniczoną zgodność wsteczną i do przodu bez unieważniania formatu.

musi wynosić 0x70 (112) bajtów(wersja 40 lub starsza)

musi wynosić 0x78 (120) bajtów(wersja 41 lub nowsza)

endian_tag uint = ENDIAN_CONSTANT tag określający kolejność bajtów. Więcej informacji znajdziesz w sekcji „ENDIAN_CONSTANT and REVERSE_ENDIAN_CONSTANT”.
link_size uint rozmiar sekcji linku lub 0, jeśli ten plik nie jest połączony statycznie
link_off uint przesunięcie od początku pliku do sekcji linku lub 0, jeśli link_size == 0. Przesunięcie, jeśli jest różne od zera, powinno być przesunięciem w sekcji link_data. Format danych, do których odwołuje się nagłówek, nie jest określony w tym dokumencie. To pole nagłówka (i poprzednie) jest przeznaczone do użycia przez implementacje w czasie wykonywania.
map_off uint przesunięcie od początku pliku do elementu mapy. Odchylenie, które musi być niezerowe, powinno być odchyleniem w sekcji data, a dane powinny być w formacie określonym przez „map_list” poniżej.
string_ids_size uint liczba ciągów znaków na liście identyfikatorów ciągów znaków
string_ids_off uint przesunięcie od początku pliku do listy identyfikatorów ciągu znaków lub 0, jeśli string_ids_size == 0 (co jest dość dziwnym przypadkiem). Przesunięcie, jeśli nie jest równe 0, powinno być przesunięciem na początek sekcji string_ids.
type_ids_size uint liczba elementów na liście identyfikatorów typu, maksymalnie 65535
type_ids_off uint przesunięcie od początku pliku do listy identyfikatorów typów lub 0, jeśli type_ids_size == 0 (co jest dość dziwnym przypadkiem). Przesunięcie, jeśli nie jest równe 0, powinno być przesunięte do początku sekcji type_ids.
proto_ids_size uint liczba elementów na liście identyfikatorów prototypów, maksymalnie 65 535
proto_ids_off uint przesunięcie od początku pliku do listy identyfikatorów prototypu lub 0, jeśli proto_ids_size == 0 (co jest dość dziwnym przypadkiem). Przesunięcie, jeśli nie jest równe 0, powinno być przesunięte do początku sekcji proto_ids.
field_ids_size uint liczba elementów na liście identyfikatorów pól,
field_ids_off uint przesunięcie od początku pliku do listy identyfikatorów pól lub 0, jeśli field_ids_size == 0. Odsunięcie, jeśli nie jest równe 0, powinno być przesunięte do początku sekcji field_ids.
method_ids_size uint liczba elementów na liście identyfikatorów metody,
method_ids_off uint przesunięcie od początku pliku do listy identyfikatorów metody lub 0, jeśli method_ids_size == 0. Odsunięcie, jeśli nie jest równe 0, powinno być przesunięte do początku sekcji method_ids.
class_defs_size uint liczba elementów na liście definicji klas
class_defs_off uint przesunięcie od początku pliku do listy definicji klas, lub 0, jeśli class_defs_size == 0 (co jest dziwnym przypadkiem szczególnym). Przesunięcie, jeśli nie jest równe 0, powinno być przesunięciem na początek sekcji class_defs.
data_size uint

Rozmiar sekcji data w bajtach. Musi być parzystą wielokrotnością sizeof(uint). (w wersji 40 lub starszej)

Nieużywane (wersja 41 lub nowsza)

data_off uint

przesunięcie od początku pliku do początku sekcji data(wersja 40 lub starsza)

Nieużywane (wersja 41 lub nowsza)

container_size uint

to pole nie istnieje. Można założyć, że jest ona równa file_size. (w wersji 40 lub starszej)

rozmiar całego pliku (w tym inne nagłówki dex i ich dane). (w wersji 41 lub nowszej)

header_offset uint

to pole nie istnieje. Można założyć, że jest ona równa 0. (w wersji 40 lub starszej)

przesunięcie od początku pliku do początku tego nagłówka. (w wersji 41 lub nowszej)

map_list

Występuje w sekcji danych

Odwołanie z header_item

Wyrównanie: 4 bajty

To lista całej zawartości pliku w kolejności. Zawiera ona pewne elementy zbędne w porównaniu z header_item, ale ma być łatwa w użyciu i przeszukiwać cały plik. dany typ musi pojawić się w mapie najwyżej raz, ale nie ma ograniczeń dotyczących tego, w jakich typach zamówień może się on pojawiać, z wyjątkiem ograniczeń wynikających z reszty formatu (np. sekcja header musi pojawić się jako pierwsza, a potem sekcja string_ids itd.). Dodatkowo wpisy mapy muszą być posortowane według początkowego przesunięcia i nie mogą się nakładać.

Nazwa Format Opis
rozmiar uint rozmiar listy (liczba wpisów).
lista map_item[size] elementów listy

Format map_item

Nazwa Format Opis
typ ushort typ elementów (patrz tabela poniżej)
unused ushort (nieużywany)
rozmiar uint liczba elementów do znalezienia w współrzędnych wskazanych przez przesunięcie;
przesunięcie uint przesunięcie od początku pliku do odpowiednich elementów.

Kody typu

Typ elementu Stała Wartość Rozmiar elementu w bajtach
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 implicit; must parse
code_item TYPE_CODE_ITEM 0x2001 implicit; must parse
string_data_item TYPE_STRING_DATA_ITEM 0x2002 implicit; must parse
debug_info_item TYPE_DEBUG_INFO_ITEM 0x2003 implicit; must parse
annotation_item TYPE_ANNOTATION_ITEM 0x2004 implicit; must parse
encoded_array_item TYPE_ENCODED_ARRAY_ITEM 0x2005 implicit; must parse
annotations_directory_item TYPE_ANNOTATIONS_DIRECTORY_ITEM 0x2006 implicit; must parse
hiddenapi_class_data_item TYPE_HIDDENAPI_CLASS_DATA_ITEM 0xF000 implicit; must parse

string_id_item

Pojawia się w sekcji string_ids.

Wyrównanie: 4 bajty

Nazwa Format Opis
string_data_off uint przesunięcie od początku pliku do danych ciągu dotyczących tego elementu. Odchylenie powinno odnosić się do lokalizacji w sekcji data, a dane powinny być w formacie określonym przez „string_data_item” poniżej. Nie ma wymagań dotyczących wyrównania przesunięcia.

string_data_item

Występuje w sekcji danych

Wyrównanie: brak (wyrównanie bajtowe)

Nazwa Format Opis
utf16_size uleb128 rozmiar tego ciągu znaków w jednostkach kodu UTF-16 (co w wielu systemach jest „długością ciągu znaków”); Jest to dekodowana długość ciągu. (zakodowana długość jest sugerowana przez pozycję bajtu 0).
dane ubyte[] seria jednostek kodu MUTF-8 (czyli oktetów lub bajtów), po której następuje bajt o wartości 0. Szczegółowe informacje o tym formacie danych oraz omówienie go znajdziesz w sekcji „Kodowanie MUTF-8 (zmodyfikowany UTF-8)” powyżej.

Uwaga: dopuszczalne jest użycie ciągu znaków zawierającego jednostki kodu zastępczego UTF-16 (czyli U+d800U+dfff) w formie zakodowanej lub w dowolnej kolejności w stosunku do zwykłego kodowania Unicode w UTF-16. Odpowiednie poziomy stosowania ciągów znaków mogą odrzucać takie nieprawidłowe kodowania.

type_id_item

Występuje w sekcji type_ids.

Wyrównanie: 4 bajty

Nazwa Format Opis
descriptor_idx uint indeksowanie listy string_ids w przypadku ciągu znaków opisowego tego typu; Ciąg musi być zgodny ze składnią TypDescriptor zdefiniowaną powyżej.

proto_id_item

Występuje w sekcji proto_ids

Wyrównanie: 4 bajty

Nazwa Format Opis
shorty_idx uint indeks na liście string_ids dla krótkiego ciągu znaków w charakterystyce tego prototypu. Ciąg znaków musi być zgodny z syntaksą ShortyDescriptor zdefiniowaną powyżej i musi odpowiadać typowi zwracanych danych oraz parametrom tego elementu.
return_type_idx uint indeks na liście type_ids dla typu zwracanego przez ten prototyp
parameters_off uint przesunięcie od początku pliku do listy typów parametrów tego prototypu lub 0, jeśli prototyp nie ma parametrów. Ten przesunięcie, jeśli jest inne niż zero, powinno znajdować się w sekcji data, a dane w tej sekcji powinny być w formacie określonym przez parametr "type_list" poniżej. Dodatkowo na liście nie powinno być żadnych odwołań do typu void.

field_id_item

Występuje w sekcji field_ids.

Wyrównanie: 4 bajty

Nazwa Format Opis
class_idx ushort indeks do listy type_ids definiującej to pole. Musi to być typ klasy, a nie tablica ani typ prymitywny.
type_idx ushort indeksowanie listy type_ids pod kątem typu tego pola;
name_idx uint indeks w liście string_ids odpowiadający nazwie tego pola. Ciąg znaków musi być zgodny ze składnią parametru MemberName zdefiniowanego powyżej.

method_id_item

Występuje w sekcji method_ids.

Wyrównanie: 4 bajty

Nazwa Format Opis
class_idx ushort indeks na liście type_ids definicji tej metody. Musi to być typ klasy lub tablicy, a nie typ prymitywny.
proto_idx ushort indeks na liście proto_ids dla prototypu tej metody
name_idx uint indeks w liście string_ids zawierający nazwę tej metody. Ciąg znaków musi być zgodny ze składnią parametru MemberName zdefiniowanego powyżej.

class_def_item

Pojawia się w sekcji class_defs.

Wyrównanie: 4 bajty

Nazwa Format Opis
class_idx uint indeks na liście type_ids dla tej klasy. Musi to być typ klasy, a nie tablica ani typ prymitywny.
access_flags uint flagi dostępu do zajęć (public, final itd.). Więcej informacji znajdziesz w sekcji „access_flags Definicje”.
superclass_idx uint indeks w liście type_ids dla superklasy lub stałą wartość NO_INDEX, jeśli ta klasa nie ma superklasy (czyli jest to klasa rdzenna, np. Object). Jeśli jest obecna, musi być typem klasy, a nie tablicą ani typem prymitywnym.
interfaces_off uint przesunięcie od początku pliku do listy interfejsów lub 0, jeśli ich nie ma. Ten przesunięcie powinno znajdować się w sekcji data, a dane w niej powinny być w formacie określonym przez parametr „type_list” poniżej. Każdy element listy musi być typem klasy (nie tablicą ani typem prymitywnym) i nie może być duplikatem.
source_file_idx uint indeks na liście string_ids dla nazwy pliku zawierającego pierwotne źródło (przynajmniej w większości) tej klasy lub wartość specjalna NO_INDEX oznaczająca brak tych informacji. debug_info_item dowolnej metody może zastąpić ten plik źródłowy, ale zakłada się, że większość klas będzie pochodzić tylko z jednego pliku źródłowego.
annotations_off uint przesunięcie od początku pliku do struktury adnotacji dla tych zajęć lub 0, jeśli w przypadku tych zajęć nie ma adnotacji. Ten przesunięcie, jeśli jest różne od zera, powinno znajdować się w sekcji data, a dane w niej powinny być w formacie określonym w sekcji „annotations_directory_item” poniżej, przy czym wszystkie elementy odwołują się do tej klasy jako definiującej.
class_data_off uint przesunięcie od początku pliku do powiązanych danych klasy dla tego elementu lub 0, jeśli dla tej klasy nie ma danych. (może się tak zdarzyć, jeśli ta klasa jest interfejsem znacznika). Odsunięcie, jeśli jest różne od 0, powinno znajdować się w sekcji data, a dane w niej powinny być w formacie określonym przez „class_data_item” poniżej, przy czym wszystkie elementy odnoszą się do tej klasy jako definiującej.
static_values_off uint przesunięcie od początku pliku do listy początkowych wartości pól static lub 0, jeśli ich nie ma (wszystkie pola static mają być inicjowane wartościami 0 lub null). To przesunięcie powinno znajdować się w sekcji data, a dane w tym miejscu powinny być w formacie określonym przez „encoded_array_item” poniżej. Rozmiar tablicy nie może być większy niż liczba pól static zadeklarowanych przez tę klasę, a elementy odpowiadają polom static w tej samej kolejności, w jakiej zostały zadeklarowane w odpowiednim elemencie field_list. Typ każdego elementu tablicy musi być zgodny z deklarowanym typem odpowiadającego mu pola. Jeśli w tablicy jest mniej elementów niż pól static, pozostałe pola są inicjowane wartościami 0 lub null odpowiednimi do typu.

call_site_id_item

Pojawia się w sekcji call_site_ids.

Wyrównanie: 4 bajty

Nazwa Format Opis
call_site_off uint przesunięcie od początku pliku do definicji strony wywołania. Odsunięcie powinno znajdować się w sekcji danych, a dane w niej powinny być w formacie określonym przez element „call_site_item” poniżej.

call_site_item

Występuje w sekcji danych

Wyrównanie: brak (wyrównanie bajtowe)

Element call_site_item to element encoded_array_item, którego elementy odpowiadają argumentom przekazanym metodzie bootstrap linker. Pierwsze 3 argumenty to:

  1. Identyfikator metody reprezentujący metodę łącznika bootstrap (VALUE_METHOD_HANDLE).
  2. Nazwa metody, którą linker bootstrap powinien rozwiązać (VALUE_STRING).
  3. Typ metody odpowiadający typowi nazwy metody do rozwiązania (VALUE_METHOD_TYPE).

Wszystkie dodatkowe argumenty to stałe wartości przekazywane do metody łącznika bootstrap. Te argumenty są przekazywane w kolejności bez konwersji typu.

Identyfikator metody reprezentujący metodę łącznika bootstrap musi mieć typ zwracania java.lang.invoke.CallSite. Pierwsze 3 typy parametrów to:

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

Typy parametrów wszystkich dodatkowych argumentów są określane na podstawie ich stałych wartości.

method_handle_item

Występuje w sekcji method_handles.

Wyrównanie: 4 bajty

Nazwa Format Opis
method_handle_type ushort typ uchwytu metody (patrz tabela poniżej)
unused ushort (nieużywany)
field_or_method_id ushort identyfikator pola lub metody w zależności od tego, czy typ uchwytu metody jest akcesorem czy wywoływaczem metody;
unused ushort (nieużywany)

Kody typu uchwytu metody

Stała Wartość Opis
METHOD_HANDLE_TYPE_STATIC_PUT 0x00 uchwyt metody to ustawiacz stałego pola (akcesor)
METHOD_HANDLE_TYPE_STATIC_GET 0x01 uchwyt metody to statycznego pola gettera (akcesora)
METHOD_HANDLE_TYPE_INSTANCE_PUT 0x02 uchwyt metody to ustawiacz pola instancji (akcesor);
METHOD_HANDLE_TYPE_INSTANCE_GET 0x03 uchwyt metody to metoda pobierająca wartości pola instancji (akcesor)
METHOD_HANDLE_TYPE_INVOKE_STATIC 0x04 uchwyt metody to wywoływacz metody statycznej
METHOD_HANDLE_TYPE_INVOKE_INSTANCE 0x05 uchwyt metody to wywoływacz metody instancji
METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR 0x06 uchwyt metody to wywoływacz metody konstruktora
METHOD_HANDLE_TYPE_INVOKE_DIRECT 0x07 Uchwyt metody to bezpośredni wywoływacz metody
METHOD_HANDLE_TYPE_INVOKE_INTERFACE 0x08 Identyfikator metody to wywoływacz metody interfejsu

class_data_item

Odwołanie z class_def_item

Występuje w sekcji danych

Wyrównanie: brak (wyrównanie bajtowe)

Nazwa Format Opis
static_fields_size uleb128 liczba pól statycznych zdefiniowanych w tym elemencie.
instance_fields_size uleb128 liczba pól instancji zdefiniowanych w tym elemencie
direct_methods_size uleb128 liczba metod bezpośrednich zdefiniowanych w tym elemencie
virtual_methods_size uleb128 liczba metod wirtualnych zdefiniowanych w tym elemencie
static_fields encoded_field[static_fields_size] zdefiniowane pola statyczne, reprezentowane jako sekwencja zakodowanych elementów; Pola muszą być posortowane według kolumny field_idx w kolejności rosnącej.
instance_fields encoded_field[instance_fields_size] zdefiniowane pola instancji, reprezentowane jako sekwencja zakodowanych elementów. Pola muszą być posortowane według kolumny field_idx w kolejności rosnącej.
direct_methods encoded_method[direct_methods_size] zdefiniowane metody bezpośrednie (dowolna z metod static, private lub konstruktora), reprezentowane jako sekwencja zakodowanych elementów. Metody muszą być posortowane według kolumny method_idx w kolejności rosnącej.
virtual_methods encoded_method[virtual_methods_size] zdefiniowane metody wirtualne (inne niż static, private lub konstruktor), reprezentowane jako sekwencja zakodowanych elementów. Ta lista nie powinna zawierać metod dziedziczonych, chyba że zostały zastąpione przez klasę, którą reprezentuje dany element. Metody muszą być posortowane według method_idx w kolejności rosnącej. method_idx metody wirtualnej nie może być taki sam jak w przypadku dowolnej metody bezpośredniej.

Uwaga: wszystkie wystąpienia elementów field_id i method_id muszą odwoływać się do tej samej klasy definiującej.

Format encoded_field

Nazwa Format Opis
field_idx_diff uleb128 indeks na liście field_ids odpowiadający tożsamości tego pola (zawiera nazwę i opis), reprezentowany jako różnica względem indeksu poprzedniego elementu na liście. Indeks pierwszego elementu na liście jest reprezentowany bezpośrednio.
access_flags uleb128 flagi dostępu do pola (public, final itd.). Więcej informacji znajdziesz w sekcji „access_flags Definicje”.

Format encoded_method

Nazwa Format Opis
method_idx_diff uleb128 indeks na liście method_ids identyfikujący tę metodę (zawiera nazwę i opis), reprezentowany jako różnica względem indeksu poprzedniego elementu na liście. Indeks pierwszego elementu na liście jest reprezentowany bezpośrednio.
access_flags uleb128 flagi dostępu metody (public, final itd.). Więcej informacji znajdziesz w sekcji „access_flags Definicje”.
code_off uleb128 przesunięcie od początku pliku do struktury kodu tej metody lub 0, jeśli ta metoda to abstract lub native. Przesunięcie powinno dotyczyć lokalizacji w sekcji data. Format danych jest określony przez „code_item” poniżej.

type_list

Odwołuje się do class_def_item i proto_id_item

Występuje w sekcji danych

Wyrównanie: 4 bajty

Nazwa Format Opis
rozmiar uint rozmiar listy (liczba wpisów).
lista type_item[size] elementów listy

Format type_item

Nazwa Format Opis
type_idx ushort indeks na liście type_ids

code_item

Odwołanie z encoded_method

Występuje w sekcji danych

Wyrównanie: 4 bajty

Nazwa Format Opis
registers_size ushort liczba rejestrów używanych przez ten kod;
ins_size ushort liczba słów argumentów przychodzących do metody, do której odnosi się ten kod;
outs_size ushort liczba słów w polu argumentu wyjściowego wymaganego przez ten kod do wywołania metody;
tries_size ushort liczba try_item w tej instancji. Jeśli wartość jest różna od 0, w tym przypadku tries będzie równe tablicy insns.
debug_info_off uint przesunięcie od początku pliku do informacji debugowania (sekwencja informacji o numerach wierszy + informacje o lokalnych zmiennych) dla tego kodu albo 0, jeśli nie ma żadnych informacji. Odsunięcie (jeśli nie jest równe 0) powinno być równe lokalizacji w sekcji data. Format danych jest określony przez „debug_info_item” poniżej.
insns_size uint rozmiar listy instrukcji w jednostkach kodu 16-bitowego;
insns ushort[insns_size] rzeczywiste tablice kodu bajtowego. Format kodu w tablicy insns jest określony w dokumentacji towarzyszącej bajtkodowi Dalvik. Pamiętaj, że chociaż ta tablica jest zdefiniowana jako tablica typu ushort, to istnieją pewne wewnętrzne struktury, które preferują wyrównanie do 4 bajtów. Jeśli plik ma odwróconą kolejność bajtów, zamiana zostanie przeprowadzona tylko w przypadku poszczególnych wystąpień ushort, a nie w większych strukturach wewnętrznych.
padding ushort (opcjonalnie) = 0 2 bajty wypełniające, aby tries był wyrównany co 4 bajty. Ten element jest widoczny tylko wtedy, gdy tries_size jest niezerowy, a insns_size jest nieparzysty.
próby try_item[tries_size] (opcjonalnie) tablicy wskazującej, gdzie w programie występują wyjątki oraz jak je obsługiwać. Elementy tablicy nie mogą się pokrywać w zakresie i muszą być uporządkowane od najniższych do najwyższych adresów. Ten element jest obecny tylko wtedy, gdy tries_size jest niezerowy.
moduły obsługi encoded_catch_handler_list (opcjonalnie) bajtów reprezentujących listę list typów łapania i powiązanych adresów przetwarzających. Każdy element try_item ma przesunięcie bajtowe w tej strukturze. Ten element jest obecny tylko wtedy, gdy tries_size jest niezerowy.

Format try_item

Nazwa Format Opis
start_addr uint adres początkowy bloku kodu objętego tą pozycją. Adres jest liczbą 16-bitowych jednostek kodu do początku pierwszej instrukcji objętej tym adresem.
insn_count ushort liczba 16-bitowych jednostek kodu objętych tym wpisem. Ostatni kod jednostka objęta (włącznie) to start_addr + insn_count - 1.
handler_off ushort przesunięcie w bajtach od początku powiązanego elementu encoded_catch_hander_list do encoded_catch_handler dla tego wpisu. Musi być przesunięty względem początku encoded_catch_handler.

Format encoded_catch_handler_list

Nazwa Format Opis
rozmiar uleb128 rozmiar tej listy (liczba wpisów).
lista encoded_catch_handler[handlers_size] rzeczywista lista list elementów obsługi, reprezentowana bezpośrednio (nie jako przesunięcia), a następnie połączona sekwencyjnie

Format encoded_catch_handler

Nazwa Format Opis
rozmiar sleb128 liczba typów połowów na tej liście. Jeśli nie jest dodatnia, jest ujemną wartością liczby typów łapacza, a łapacze są poprzedzone przez ogólny przetwarzacz. Na przykład: size0 oznacza, że istnieje uniwersalny typ, ale nie ma żadnych typów z wyraźnie określonymi regułami. size z 2 oznacza, że są 2 explicitly typed catches i brak catch-all. A size-1 oznacza, że jest jeden typowany element i element uniwersalny.
moduły obsługi encoded_type_addr_pair[abs(size)] strumień zakodowanych elementów abs(size), po jednym dla każdego typu, w kolejności, w jakiej te typy powinny być testowane.
catch_all_addr uleb128 (opcjonalnie) adres bajtowy obsługi typu catch-all. Ten element jest obecny tylko wtedy, gdy size ma wartość niezerową.

Format encoded_type_addr_pair

Nazwa Format Opis
type_idx uleb128 indeks na liście type_ids odpowiadający typowi wyjątku do przechwycenia
addr uleb128 adres bajtowy powiązanego modułu obsługi wyjątków.

debug_info_item

Odwołanie z poziomu kodu_item

Występuje w sekcji danych

Wyrównanie: brak (wyrównanie bajtowe)

Każda wartość debug_info_item definiuje maszynę stanów kodowaną bajtami, która jest inspirowana DWARF3. Po interpretacji emituje tablicę pozycji i (opcjonalnie) informacje o zmiennych lokalnych dla code_item. Sekwencja zaczyna się nagłówkiem o zmiennej długości (długość zależy od liczby parametrów metody), po którym następują bajty kodu bajtowego maszyny stanów, a kończy się bajtem DBG_END_SEQUENCE.

Maszyna stanów składa się z 5 rejestrów. Rejestr address reprezentuje przesunięcie instrukcji w powiązanym insns_item w 16-bitowych jednostkach kodu. Rejestr address zaczyna się od wartości 0 na początku każdej sekwencji debug_info i musi monotonicznie rosnąć. Rejestr line wskazuje, który numer wiersza źródła powinien być powiązany z kolejną pozycją w tabeli generowanej przez maszynę stanów. Jest on inicjowany w nagłówku sekwencji i może się zmieniać w kierunku dodatnim lub ujemnym, ale nigdy nie może być mniejszy niż 1. Rejestr source_file to plik źródłowy, do którego odnoszą się wpisy numeru wiersza. Jest on inicjowany wartością source_file_idxclass_def_item. Pozostałe 2 zmiennych, prologue_endepilogue_begin, to flagi logiczne (inicjowane jako false), które wskazują, czy emitowana pozycja ma być uważana za prolog czy epilog metody. Maszyna stanów musi też śledzić nazwę i typ ostatniej zmiennej lokalnej w każdym rejestrze kodu DBG_RESTART_LOCAL.

Nagłówek wygląda tak:

Nazwa Format Opis
line_start uleb128 początkowa wartość rejestru line maszyny stanów. Nie reprezentuje rzeczywistego wpisu pozycji.
parameters_size uleb128 liczba zakodowanych nazw parametrów. Należy utworzyć po jednym dla każdego parametru metody, z wyjątkiem parametru this metody instancji, jeśli taki występuje.
parameter_names uleb128p1[parameters_size] indeks ciągu znaków nazwy parametru metody. Zaszyfrowana wartość NO_INDEX oznacza, że nie ma nazwy dostępnej dla powiązanego parametru. Opis typu i podpis są implikowane z opisu metody i podpisu.

Wartości kodu bajtowego:

Nazwa Wartość Format Argumenty Opis
DBG_END_SEQUENCE 0x00 (brak) kończy sekwencję danych debugowania w przypadku code_item
DBG_ADVANCE_PC 0x01 uleb128 addr_diff addr_diff: kwota do dodania do rejestru adresów przesuwa rejestr adresów bez emitowania pozycji
DBG_ADVANCE_LINE 0x02 sleb128 line_diff line_diff: kwota, o jaką ma się zmienić rejestr linii przesuwa rejestr linii bez emitowania pozycji
DBG_START_LOCAL 0x03 uleb128 register_num
uleb128p1 name_idx
uleb128p1 type_idx
register_num: rejestr, który będzie zawierać lokalną zmienną
name_idx: indeks ciągu znaków nazwy
type_idx: indeks typu
wprowadza zmienną lokalną w bieżącym adresie. Możesz użyć wartości name_idx lub type_idx, aby wskazać, że ta wartość jest nieznana.NO_INDEX
DBG_START_LOCAL_EXTENDED 0x04 uleb128 register_num
uleb128p1 name_idx
uleb128p1 type_idx
uleb128p1 sig_idx
register_num: rejestr, który będzie zawierać lokalną wartość
name_idx: indeks ciągu znaków nazwy
type_idx: indeks typu
sig_idx: indeks ciągu znaków sygnatury typu
wprowadza lokalny typ z podpisem w bieżącym adresie. Wartość name_idx, type_idx lub sig_idx może być NO_INDEX, aby wskazać, że wartość jest nieznana. (Jeśli sig_idx jest -1, te same dane można przedstawić bardziej efektywnie za pomocą kodu operacji DBG_START_LOCAL).

Uwaga: poniżej w sekcji „dalvik.annotation.Signature” znajdziesz informacje o ograniczeniach dotyczących obsługi podpisów.

DBG_END_LOCAL 0x05 uleb128 register_num register_num: rejestr zawierający lokalny oznacza bieżącą zmienną lokalną jako nieobejmowaną przez bieżący adres;
DBG_RESTART_LOCAL 0x06 uleb128 register_num register_num: zarejestruj się, aby ponownie uruchomić ponownie wprowadza lokalną zmienną w bieżącym adresie. Nazwa i typ są takie same jak w ostatnim lokalnym rekordzie w określonym rejestrze.
DBG_SET_PROLOGUE_END 0x07 (brak) ustawia rejestr maszyny stanów prologue_end, wskazując, że dodana pozycja następna powinna być traktowana jako koniec prologu metody (odpowiednie miejsce na punkt przerwania metody). Rejester prologue_end jestczyszczany przez dowolny kod operacji specjalnej (>= 0x0a).
DBG_SET_EPILOGUE_BEGIN 0x08 (brak) ustawia rejestr maszyny stanów epilogue_begin, wskazując, że dodany następny wpis pozycji powinien być traktowany jako początek epilogu metody (odpowiednie miejsce do zawieszenia wykonania przed wyjściem z metody). Rejestr epilogue_begin jest opróżniany przez dowolny kod operacji specjalnej (>= 0x0a).
DBG_SET_FILE 0x09 uleb128p1 name_idx name_idx: indeks ciągu znaków nazwy pliku źródłowego; NO_INDEX, jeśli jest nieznany oznacza, że wszystkie kolejne wpisy numeru wiersza odwołują się do tej nazwy pliku źródłowego, a nie do nazwy domyślnej określonej w pliku code_item
Kody operacji specjalne 0x0a…0xff (brak) przesuwa rejestry lineaddress, wysyła wpis pozycji oraz czyści prologue_endepilogue_begin. Opis znajdziesz poniżej.

Specjalne kody operacji

Kody operacji o wartościach od 0x0a do 0xff (łącznie) przesuwają rejestry lineaddress o niewielką wartość, a następnie emitują nowy wpis w tabeli pozycji. Formuła przyrostów:

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

Odwołanie z class_def_item

Występuje w sekcji danych

Wyrównanie: 4 bajty

Nazwa Format Opis
class_annotations_off uint przesunięcie od początku pliku do adnotacji wprowadzonych bezpośrednio w klasie lub 0, jeśli klasa nie zawiera adnotacji bezpośrednich. Odsunięcie, jeśli nie jest równe 0, powinno wskazywać lokalizację w sekcji data. Format danych jest określony przez „annotation_set_item” poniżej.
fields_size uint liczba pól oznaczonych przez ten element
annotated_methods_size uint liczba metod oznaczonych przez ten element
annotated_parameters_size uint liczba list parametrów metody oznaczonych przez ten element
field_annotations field_annotation[fields_size] (opcjonalnie) lista powiązanych adnotacji pól. Elementy listy muszą być posortowane w kolejności rosnącej według kolumny field_idx.
method_annotations method_annotation[methods_size] (opcjonalnie) lista powiązanych adnotacji metody. Elementy listy muszą być posortowane w kolejności rosnącej według kolumny method_idx.
parameter_annotations parameter_annotation[parameters_size] (opcjonalnie) lista powiązanych adnotacji parametrów metody; Elementy listy muszą być posortowane w kolejności rosnącej według kolumny method_idx.

Uwaga: wszystkie wystąpienia elementów field_id i method_id muszą odwoływać się do tej samej klasy definiującej.

format field_annotation

Nazwa Format Opis
field_idx uint indeks na liście field_ids odpowiadający tożsamości pola, które ma być opatrzone adnotacją;
annotations_off uint przesunięcie od początku pliku do listy adnotacji dla tego pola. Przesunięcie powinno być ustawione na lokalizację w sekcji data. Format danych jest określony przez „annotation_set_item” poniżej.

format method_annotation

Nazwa Format Opis
method_idx uint indeks w liście method_ids zawierający tożsamość metody, której dotyczy adnotacja;
annotations_off uint przesunięcie od początku pliku do listy adnotacji dla metody. Przesunięcie powinno dotyczyć lokalizacji w sekcji data. Format danych jest określony przez „annotation_set_item” poniżej.

Format parameter_annotation

Nazwa Format Opis
method_idx uint indeks w liście method_ids odpowiadający metodzie, której parametry są adnotowane
annotations_off uint przesunięcie od początku pliku do listy adnotacji dla parametrów metody. Przesunięcie powinno dotyczyć lokalizacji w sekcji data. Format danych jest określony przez „annotation_set_ref_list” poniżej.

annotation_set_ref_list

Odwołanie z elementu parameter_annotations_item

Występuje w sekcji danych

Wyrównanie: 4 bajty

Nazwa Format Opis
rozmiar uint rozmiar listy (liczba wpisów).
lista annotation_set_ref_item[size] elementów listy

Format annotation_set_ref_item

Nazwa Format Opis
annotations_off uint przesunięcie od początku pliku do zestawu adnotacji, na który się odwołuje lub 0, jeśli nie ma adnotacji dla tego elementu. Jeśli przesunięcie jest inne niż zero, powinno wskazywać lokalizację w sekcji data. Format danych jest określony przez „annotation_set_item” poniżej.

annotation_set_item

Odwołuje się do elementów annotations_directory_item, field_annotations_item, method_annotations_item i annotation_set_ref_item.

Występuje w sekcji danych

Wyrównanie: 4 bajty

Nazwa Format Opis
rozmiar uint rozmiar zbioru (liczba wpisów).
wpisy annotation_off_item[size] elementów zestawu. Elementy muszą być posortowane w kolejności rosnącej według kolumny type_idx.

Format annotation_off_item

Nazwa Format Opis
annotation_off uint przesunięcie od początku pliku do adnotacji. Odchylenie powinno odnosić się do lokalizacji w sekcji data, a format danych w tej lokalizacji jest określony przez parametr „annotation_item” poniżej.

annotation_item

Odwołanie z annotation_set_item

Występuje w sekcji danych

Wyrównanie: brak (wyrównanie bajtowe)

Nazwa Format Opis
widoczność ubyte zamierzona widoczność tej adnotacji (patrz poniżej);
adnotacja encoded_annotation zakodowane treści adnotacji w formacie opisanym w sekcji „Format encoded_annotation” w sekcji „Kodowanie encoded_value” powyżej.

Wartości widoczności

Oto opcje pola visibility w elementach annotation_item:

Nazwa Wartość Opis
VISIBILITY_BUILD 0x00 mają być widoczne tylko w czasie kompilacji (np. podczas kompilowania innego kodu);
VISIBILITY_RUNTIME 0x01 mają być widoczne w czasie wykonywania.
VISIBILITY_SYSTEM 0x02 widoczne w czasie wykonywania, ale tylko dla systemu bazowego (a nie dla zwykłego kodu użytkownika);

encoded_array_item

Odwołanie z class_def_item

Występuje w sekcji danych

Wyrównanie: brak (wyrównanie bajtowe)

Nazwa Format Opis
wartość encoded_array bajty reprezentujące zakodowaną wartość tablicy w formacie określonym przez „encoded_array Format” w sekcji „encoded_value kodowanie” powyżej.

hiddenapi_class_data_item

Ta sekcja zawiera dane o interfejsach z ograniczonym dostępem używanych przez poszczególne klasy.

Uwaga: funkcja ukrytego interfejsu API została wprowadzona w Androidzie 10.0 i dotyczy tylko plików DEX klas na ścieżce uruchamiania. Lista flag opisanych poniżej może zostać rozszerzona w kolejnych wersjach Androida. Więcej informacji znajdziesz w artykule o ograniczeniach interfejsów innych niż SDK.

Nazwa Format Opis
rozmiar uint łączny rozmiar sekcji.
przesunięcia uint[] tablica przesunięć indeksowana przez class_idx. Wpis tablicy o wartości 0 w indeksie class_idx oznacza, że albo nie ma danych dla tego class_idx, albo wszystkie ukryte flagi interfejsu API mają wartość 0. W przeciwnym razie wpis tablicy ma wartość różną od 0 i zawiera przesunięcie od początku sekcji do tablicy ukrytych flag interfejsu API dla tego class_idx.
flagi uleb128[] złączone tablice ukrytych flag interfejsu API dla każdej klasy. Możliwe wartości flagi zostały opisane w tabeli poniżej. Flagi są kodowane w tej samej kolejności, w jakiej pola i metody są kodowane w danych klasy.

Typy flag ograniczeń:

Nazwa Wartość Opis
biała lista 0 Interfejsy, których można używać swobodnie i które są obsługiwane w ramach oficjalnie udokumentowanego frameworka Androida Package Index.
szara lista 1 interfejsy spoza pakietu SDK, których można używać niezależnie od docelowego poziomu interfejsu API aplikacji;
zablokuj 2 interfejsów spoza pakietu SDK, których nie można używać niezależnie od docelowego poziomu interfejsu API aplikacji; Uzyskanie dostępu do jednego z tych interfejsów powoduje błąd podczas działania.
greylist‑max‑o 3 interfejsy spoza pakietu SDK, które można używać w przypadku Androida 8.x i starszych, chyba że są ograniczone;
greylist‑max‑p 4 interfejsy spoza pakietu SDK, które można używać w Androidzie 9.x, chyba że są ograniczone;
greylist‑max‑q 5 interfejsy spoza pakietu SDK, które można używać w Androidzie 10.x, chyba że są ograniczone;
greylist‑max‑r 6 Interfejsy spoza pakietu SDK, których można używać w Androidzie 11.x, chyba że są ograniczone.

Adnotacje systemowe

Adnotacje systemowe służą do reprezentowania różnych informacji o klasach (oraz metodach i polach). Te informacje są zazwyczaj dostępne tylko pośrednio przez kod klienta (niesystemowy).

Adnotacje systemowe są reprezentowane w plikach .dex jako adnotacje z widocznością ustawioną na VISIBILITY_SYSTEM.

dalvik.annotation.AnnotationDefault

Występuje w metodach w interfejsach adnotacji

Do każdego interfejsu adnotacji, który ma wskazywać domyślne wiązania, jest dołączona adnotacja AnnotationDefault.

Nazwa Format Opis
wartość Adnotacja domyślne powiązania tej adnotacji, reprezentowane jako adnotacja tego typu. Adnotacja nie musi zawierać wszystkich nazw zdefiniowanych przez adnotację; brakujące nazwy po prostu nie mają wartości domyślnych.

dalvik.annotation.EnclosingClass

Pojawia się na zajęciach

Do każdej klasy, która jest zdefiniowana jako element innej klasy lub jest anonimowa, ale nie jest zdefiniowana w ciele metody (np. syntetyczna klasa wewnętrzna), jest dołączona adnotacja EnclosingClass. Każda klasa, która ma tę adnotację, musi mieć też adnotację InnerClass. Dodatkowo zajęcia nie mogą mieć zarówno adnotacji EnclosingClass, jak i EnclosingMethod.

Nazwa Format Opis
wartość Kategoria klasa, która najbardziej pasuje do tej klasy pod względem leksykalnym

dalvik.annotation.EnclosingMethod

Pojawia się na zajęciach

Do każdej klasy zdefiniowanej w ciele metody jest dołączona adnotacja EnclosingMethod. Każda klasa, która ma tę adnotację, musi mieć też adnotację InnerClass. Dodatkowo zajęcia nie mogą mieć jednocześnie adnotacji EnclosingClass i EnclosingMethod.

Nazwa Format Opis
wartość Metoda metoda, która najlepiej określa zakres leksykalny tej klasy;

dalvik.annotation.InnerClass

Pojawia się na zajęciach

Do każdej klasy, która jest zdefiniowana w zakresie leksykalnym definicji innej klasy, jest dołączona adnotacja InnerClass. Każda klasa, która ma tę adnotację, musi mieć adnotację EnclosingClass lub adnotację EnclosingMethod.

Nazwa Format Opis
nazwa Ciąg znaków pierwotnie zadeklarowana prosta nazwa tej klasy (bez prefiksu pakietu). Jeśli zajęcia są anonimowe, ich nazwa to null.
accessFlags int pierwotnie zadeklarowane flagi dostępu klasy (które mogą różnić się od flag skutecznych z powodu niezgodności modeli wykonania języka źródłowego i docelowej maszyny wirtualnej);

dalvik.annotation.MemberClasses

Pojawia się na zajęciach

Do każdej klasy dołączona jest adnotacja MemberClasses, która deklaruje klasy członkowskie. (Klasa członkowska jest klasą wewnętrzną bezpośrednio zawierającą nazwę).

Nazwa Format Opis
wartość Class[] tablica klas członków

dalvik.annotation.MethodParameters

Pojawia się w metodach

Uwaga: ta adnotacja została dodana po Androidzie 7.1. Jego obecność w poprzednich wersjach Androida zostanie zignorowana.

Adnotacja MethodParameters jest opcjonalna i może służyć do udostępniania metadanych parametrów, takich jak nazwy i modyfikatory parametrów.

Adnotację można bezpiecznie pominąć w metodzie lub konstruktorze, jeśli metadane parametru nie są wymagane w czasie wykonywania. Za pomocą funkcji java.lang.reflect.Parameter.isNamePresent() możesz sprawdzić, czy w przypadku danego parametru występują metadane. Jeśli nie, powiązane metody odbicia, takie jak java.lang.reflect.Parameter.getName(), powrócą do domyślnego zachowania w czasie wykonywania.

W przypadku dołączania metadanych parametrów kompilatory muszą uwzględniać informacje o wygenerowanych klasach, takich jak enumy, ponieważ metadane parametrów obejmują informacje o tym, czy parametr jest syntetyczny, czy wymagany.

Adnotacja MethodParameters opisuje tylko poszczególne parametry metody. Dlatego kompilatory mogą całkowicie pominąć adnotację w przypadku konstruktorów i metod bez parametrów, aby zmniejszyć rozmiar kodu i zwiększyć wydajność w czasie wykonywania.

Tablice opisane poniżej muszą mieć taki sam rozmiar jak struktura dex method_id_item powiązana z metodą. W przeciwnym razie w czasie wykonywania zostanie wygenerowany błąd java.lang.reflect.MalformedParametersException.

Oznacza to, że method_id_item.proto_idx -> proto_id_item.parameters_off -> type_list.size musi być takie samo jak names().length i accessFlags().length.

Funkcja MethodParameters opisuje wszystkie formalne parametry metody, nawet te, które nie są jawnie ani domyślnie zadeklarowane w kodzie źródłowym. Dlatego rozmiar tablic może się różnić od podpisu lub innych informacji metadanych, które są oparte tylko na jawnych parametrach zadeklarowanych w kodzie źródłowym. MethodParameters nie będzie też zawierać żadnych informacji o parametrach typu annotation receiver, które nie występują w rzeczywistej sygnaturze metody.

Nazwa Format Opis
nazwy Ciąg znaków[] Nazwy parametrów formalnych powiązanej metody. Tablica nie może być pusta, ale musi być pusta, jeśli nie ma parametrów formalnych. Wartość w tablicy musi być null, jeśli parametr formalny o tym indeksie nie ma nazwy.
Jeśli ciągi znaków nazw parametrów są puste lub zawierają „.”, „\”, „[” lub „/”, to w czasie wykonywania zostanie rzucony błądjava.lang.reflect.MalformedParametersException.
accessFlags int[] Flagi dostępu parametrów formalnych powiązanej metody. Tablica nie może być pusta, ale musi być pusta, jeśli nie ma formalnych parametrów.
Ta wartość to maska bitowa o tych wartościach:
  • 0x0010 : final, parametr został zadeklarowany jako finalny
  • 0x1000 : wartość syntetyczna, parametr został wprowadzony przez kompilator
  • 0x8000 : wymagany, parametr jest syntetyczny, ale również sugerowany przez specyfikację języka.
Jeśli jakiekolwiek bity są ustawione poza tym zbiorem, w czasie wykonywania zostanie rzucony wyjątek java.lang.reflect.MalformedParametersException.

dalvik.annotation.Signature

Występuje w klasach, polach i metodach

Do każdej klasy, pola lub metody, która jest zdefiniowana w terminach bardziej złożonego typu niż type_id_item, jest dołączona adnotacja Signature. Format .dex nie definiuje formatu podpisów; ma on jedynie reprezentować podpisy wymagane przez język źródłowy w celu prawidłowego wdrożenia jego semantyki. Dlatego podpisy nie są zwykle analizowane (ani weryfikowane) przez implementacje maszyn wirtualnych. Podpisy są po prostu przekazywane do interfejsów API i narzędzi wyższego poziomu (takich jak debugery). Wszelkie użycie podpisu powinno być napisane w taki sposób, aby nie zakładać, że otrzymano tylko prawidłowe podpisy, i w jasny sposób chronić się przed możliwością otrzymania nieprawidłowego podpisu pod względem składni.

Ponieważ ciągi podpisu zwykle zawierają wiele powtarzających się treści, adnotacja Signature jest definiowana jako tabelka ciągów tekstowych, w których duplikowane elementy odwołują się do tych samych danych źródłowych, a podpis jest traktowany jako konkatenacja wszystkich ciągów w tabelce. Nie ma żadnych reguł dotyczących tego, jak rozbić podpis na osobne ciągi znaków. To zależy wyłącznie od narzędzi generujących pliki .dex.

Nazwa Format Opis
wartość Ciąg znaków[] sygnaturę tej klasy lub elementu jako tablicę ciągów, które mają zostać złączone

dalvik.annotation.Throws

Pojawia się w metodach

Do każdej metody, która deklaruje wyrzucanie co najmniej 1 typu wyjątku, jest dołączona adnotacja Throws.

Nazwa Format Opis
wartość Class[] tablica typów wyjątków, które zostały zgłoszone