W tym dokumencie opisujemy układ i zawartość plików .dex
, które służą do przechowywania zestawu definicji klas i powiązanych z nimi danych dodatkowych.
Przewodnik po typach
Nazwa | Opis |
---|---|
bajt | 8-bitowa liczba całkowita ze znakiem |
ubyte | 8-bitowa liczba całkowita bez znaku |
krótki | 16-bitowa liczba całkowita ze znakiem, little-endian |
ushort | 16-bitowa liczba całkowita bez znaku, little-endian |
int | 32-bitowa liczba całkowita ze znakiem, kolejność bajtów little-endian |
uint | 32-bitowa liczba całkowita bez znaku, little-endian |
długi | 64-bitowa liczba całkowita ze znakiem, little-endian |
ulung | 64-bitowa liczba całkowita bez znaku, little-endian |
sleb128 | liczba całkowita ze znakiem LEB128, o zmiennej długości (patrz poniżej); |
uleb128 | liczba całkowita bez znaku LEB128 o zmiennej długości (patrz poniżej) |
uleb128p1 | niepodpisana liczba 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 liczb całkowitych ze znakiem lub bez znaku. Format został zaczerpnięty ze specyfikacji DWARF3. W pliku .dex
kodowanie LEB128 jest używane tylko do kodowania 32-bitowych wartości.
Każda wartość zakodowana w formacie LEB128 składa się z 1–5 bajtów, które razem reprezentują pojedynczą 32-bitową wartość. Każdy bajt ma ustawiony najbardziej znaczący bit, z wyjątkiem ostatniego bajtu w sekwencji, który ma wyczyszczony najbardziej znaczący bit. Pozostałe 7 bitów każdego bajtu to ładunek. Najmniej znaczące 7 bitów ilości znajduje się w pierwszym bajcie, kolejne 7 bitów w drugim bajcie itd. W przypadku liczby LEB128 ze znakiem (sleb128
) najbardziej znaczący bit ładunku ostatniego bajtu w sekwencji jest rozszerzany ze znakiem, aby uzyskać wartość końcową. W przypadku liczb bez znaku (uleb128
) wszystkie bity, które nie są wyraźnie reprezentowane, są interpretowane jako 0
.
Diagram bitowy 2-bajtowej wartości LEB128 | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Pierwszy bajt | Drugi bajt | ||||||||||||||
1 |
bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | 0 |
bit13 | bit12 | bit11 | bit10 | bit9 | bit8 | bit7 |
Wariant uleb128p1
służy do przedstawiania wartości ze znakiem, gdzie reprezentacja jest wartością plus jeden zakodowaną jako uleb128
. Dzięki temu kodowanie liczby -1
(alternatywnie traktowanej jako wartość bez znaku 0xffffffff
) – ale nie żadnej innej liczby ujemnej – zajmuje tylko 1 bajt. Jest to przydatne w tych przypadkach, w których reprezentowana liczba musi być nieujemna lub równa -1
(lub 0xffffffff
), a inne wartości ujemne są niedozwolone (lub gdy duże wartości bez znaku są mało prawdopodobne).
Oto kilka przykładów formatów:
Zakodowana sekwencja | Jak sleb128 |
Jak uleb128 |
Jak uleb128p1 |
---|---|---|---|
00 | 0 | 0 | -1 |
01 | 1 | 1 | 0 |
7f | -1 | 127 | 126 |
80 7f | -128 | 16256 | 16255 |
Układ pliku
Nazwa | Format | Opis |
---|---|---|
nagłówek | header_item | nagłówek, |
string_ids | string_id_item[] | lista identyfikatorów ciągów znaków. Są to identyfikatory wszystkich ciągów znaków używanych w tym pliku, zarówno do nazewnictwa wewnętrznego (np. deskryptory typów), jak i jako stałe obiekty, do których odwołuje się kod. Lista musi być posortowana według zawartości ciągu znaków z użyciem wartości punktów kodowych UTF-16 (nie w sposób zależny od ustawień regionalnych) i nie może zawierać zduplikowanych wpisów. |
type_ids | type_id_item[] | listę identyfikatorów typów. Są to identyfikatory wszystkich typów (klas, tablic lub typów prostych), do których odwołuje się ten plik, niezależnie od tego, czy są one w nim zdefiniowane. Lista musi być posortowana według indeksu string_id i nie może zawierać zduplikowanych pozycji.
|
proto_ids | proto_id_item[] | lista identyfikatorów prototypów metod. Są to identyfikatory wszystkich prototypów, do których odwołuje się ten plik. Lista musi być posortowana według typu zwracanego (według indeksu type_id ) w kolejności głównej, a następnie według listy argumentów (porządek leksykograficzny, poszczególne argumenty posortowane według indeksu type_id ). Lista nie może zawierać zduplikowanych pozycji.
|
field_ids | field_id_item[] | listę identyfikatorów pól. Są to identyfikatory wszystkich pól, do których odwołuje się ten plik, niezależnie od tego, czy są w nim zdefiniowane. Ta lista musi być posortowana, przy czym typ definiujący (według indeksu type_id ) jest głównym porządkiem, nazwa pola (według indeksu string_id ) jest porządkiem pośrednim, a typ (według indeksu type_id ) jest porządkiem pomocniczym. Lista nie może zawierać zduplikowanych pozycji.
|
method_ids | method_id_item[] | lista identyfikatorów metod. Są to identyfikatory wszystkich metod, do których odwołuje się ten plik, niezależnie od tego, czy są w nim zdefiniowane. Ta lista musi być posortowana, przy czym typ definiujący (według indeksu type_id ) jest głównym porządkiem, nazwa metody (według indeksu string_id ) jest porządkiem pośrednim, a prototyp metody (według indeksu proto_id ) jest porządkiem podrzędnym. Lista nie może zawierać zduplikowanych pozycji.
|
class_defs | class_def_item[] | listę definicji klas. Klasy muszą być uporządkowane w taki sposób, aby klasa nadrzędna i zastosowane interfejsy danej klasy pojawiały się na liście wcześniej niż klasa odwołująca się. Ponadto nieprawidłowe jest, aby definicja klasy o tej samej nazwie pojawiała się na liście więcej niż raz. |
call_site_ids | call_site_id_item[] | lista identyfikatorów witryn połączeń. Są to identyfikatory wszystkich witryn połączeń, do których odwołuje się ten plik, niezależnie od tego, czy są one w nim zdefiniowane. Ta lista musi być posortowana w kolejności rosnącej według kolumny call_site_off .
|
method_handles | method_handle_item[] | lista uchwytów metod. Lista wszystkich uchwytów metod, do których odwołuje się ten plik, niezależnie od tego, czy są one w nim zdefiniowane. Lista nie jest posortowana i może zawierać duplikaty, które logicznie odpowiadają różnym instancjom uchwytów metod. |
dane | ubyte[] | obszar danych zawierający wszystkie dane pomocnicze do tabel wymienionych powyżej; Różne elementy mają różne wymagania dotyczące wyrównania, a w razie potrzeby przed każdym elementem wstawiane są bajty dopełniające, aby uzyskać 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. W niepołączonych plikach ta sekcja jest pusta, a implementacje środowiska wykonawczego mogą jej używać w dowolny sposób. |
Format kontenera
Wersja 41 wprowadza nowy format kontenera danych DEX, który ma na celu oszczędzanie miejsca. Ten format kontenera umożliwia łączenie kilku logicznych plików DEX w jeden plik fizyczny. Nowy format to w większości proste połączenie plików w poprzednim formacie, ale występują pewne różnice:
file_size
to rozmiar pliku logicznego, a nie fizycznego. Można go używać do iteracji po wszystkich plikach logicznych w kontenerze.- Logiczne pliki DEX mogą odwoływać się do dowolnych późniejszych danych w kontenerze (ale nie do wcześniejszych). Dzięki temu pliki DEX mogą udostępniać sobie dane, np. ciągi znaków.
- Wszystkie przesunięcia są względne w stosunku do pliku fizycznego. Brak przesunięcia względem nagłówka. Dzięki temu sekcje z przesunięciami można udostępniać 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.
- Atrybuty
data_size
idata_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ła tablica/ciąg znaków DEX_FILE_MAGIC
to lista bajtów, które muszą znajdować się na początku pliku .dex
, aby został on rozpoznany jako taki. Wartość celowo zawiera znak nowego wiersza ("\n"
lub 0x0a
) i znak null ("\0"
lub 0x00
), aby ułatwić wykrywanie niektórych form uszkodzenia. Wartość ta zawiera też numer wersji formatu w postaci 3-cyfrowej liczby dziesiętnej, która powinna rosnąć monotonicznie wraz z ewolucją formatu.
ubyte[8] DEX_FILE_MAGIC = { 0x64 0x65 0x78 0x0a 0x30 0x33 0x39 0x00 } = "dex\n039\0"
Uwaga: obsługa wersji 041
formatu została dodana w Androidzie 16, który obsługuje format kontenera.
Uwaga: obsługa wersji 040
formatu została dodana w Androidzie 10.0, co rozszerzyło zestaw dozwolonych znaków w SimpleNames.
Uwaga: obsługa wersji 039
formatu została dodana w Androidzie 9.0, w którym wprowadzono 2 nowe kody bajtowe: const-method-handle
i const-method-type
. (Każdy z nich jest opisany w tabeli Podsumowanie zestawu kodu bajtowego). W Androidzie 10 wersja 039
rozszerza format pliku DEX o ukryte informacje o interfejsie API, które mają zastosowanie tylko do plików DEX na ścieżce klasy rozruchowej.
Uwaga: obsługa wersji 038
formatu została dodana w Androidzie 8.0. Wersja 038
dodała nowe kody bajtowe (invoke-polymorphic
i invoke-custom
) oraz dane do obsługi metod.
Uwaga: obsługa wersji 037
formatu została dodana w Androidzie 7.0. Przed wersją 037
większość wersji Androida korzystała z wersji 035
tego formatu. Jedyna różnica między wersjami 035
i 037
polega na dodaniu metod domyślnych i dostosowaniu invoke
.
Uwaga: co najmniej kilka wcześniejszych wersji formatu było używanych w ogólnodostępnych wersjach oprogramowania. 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 platformy Android (luty–marzec 2008 r.). W wielu aspektach te wcześniejsze wersje formatu znacznie różnią się od wersji opisanej w tym dokumencie.
ENDIAN_CONSTANT i REVERSE_ENDIAN_CONSTANT
Umieszczony w header_item
Stała ENDIAN_CONSTANT
służy do określania kolejności bajtów w pliku, w którym się znajduje. Chociaż standardowy format .dex
jest zapisywany w formacie little-endian, implementacje mogą zamieniać bajty. Jeśli implementacja napotka nagłówek, którego endian_tag
ma wartość REVERSE_ENDIAN_CONSTANT
zamiast ENDIAN_CONSTANT
, będzie wiedzieć, że plik został zamieniony bajtami z oczekiwanej formy.
uint ENDIAN_CONSTANT = 0x12345678; uint REVERSE_ENDIAN_CONSTANT = 0x78563412;
NO_INDEX
Umieszczony w elementach class_def_item i debug_info_item
Stała NO_INDEX
służy do wskazania, ż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 flag dostępu
Umieszczony w elementach class_def_item, encoded_field, encoded_method i InnerClass
Pola bitowe tych flag służą do wskazywania dostępności i ogólnych właściwości klas oraz elementów klas.
Nazwa | Wartość | W przypadku zajęć (i adnotacji InnerClass ) |
For Fields | 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 skonstruowany z odwołaniem do zewnętrznego
this |
static : globalny dla klasy definiującej |
static : nie przyjmuje argumentu this |
ACC_FINAL | 0x10 | final : nie można utworzyć podklasy |
final : niezmienny po utworzeniu |
final : nie można zastąpić |
ACC_SYNCHRONIZED | 0x20 | synchronized : powiązany zamek jest automatycznie uzyskiwany
w trakcie wywołania tej metody. Uwaga: to ustawienie jest prawidłowe tylko wtedy, gdy ustawiona jest też wartość parametru |
||
ACC_VOLATILE | 0x40 | volatile : specjalne reguły dostępu, które pomagają w zapewnieniu bezpieczeństwa wątków; |
||
ACC_BRIDGE | 0x40 | metoda pomostowa, dodawana automatycznie przez kompilator jako bezpieczny typowo pomost | ||
ACC_TRANSIENT | 0x80 | transient : nie zapisywać w przypadku domyślnej serializacji |
||
ACC_VARARGS | 0x80 | ostatni argument powinien być traktowany przez kompilator jako argument „rest” | ||
ACC_NATIVE | 0x100 | native : zaimplementowane w kodzie natywnym |
||
ACC_INTERFACE | 0x200 | interface : klasa abstrakcyjna z możliwością wielokrotnej implementacji |
||
ACC_ABSTRACT | 0x400 | abstract : nie można bezpośrednio utworzyć instancji |
abstract : nie zaimplementowano w tej klasie |
|
ACC_STRICT | 0x800 | strictfp : ścisłe reguły arytmetyki zmiennoprzecinkowej |
||
ACC_SYNTHETIC | 0x1000 | nie jest zdefiniowany bezpośrednio w kodzie źródłowym, | nie jest zdefiniowany bezpośrednio w kodzie źródłowym, | nie jest zdefiniowany bezpośrednio w kodzie źródłowym, |
ACC_ANNOTATION | 0x2000 | zadeklarowany jako klasa adnotacji, | ||
ACC_ENUM | 0x4000 | zadeklarowany jako typ wyliczeniowy, | zadeklarowany jako wartość wyliczeniowa. | |
(nieużywane) | 0x8000 | |||
ACC_CONSTRUCTOR | 0x10000 | metoda konstruktora (inicjator klasy lub instancji); | ||
ACC_DECLARED_ SYNCHRONIZED |
0x20000 | zadeklarowano synchronized . Uwaga: nie ma to wpływu na wykonanie (poza odzwierciedleniem tej flagi). |
InnerClass
. Nie może być nigdy w przypadku class_def_item
.
Zmodyfikowane kodowanie UTF-8
Aby ułatwić obsługę starszych wersji, format .dex
koduje dane tekstowe w zmodyfikowanej formie UTF-8, która jest standardem de facto i którą będziemy dalej nazywać MUTF-8. Ten format jest identyczny ze standardowym formatem UTF-8, z wyjątkiem:
- Używane są tylko kodowania 1-, 2- i 3-bajtowe.
- Punkty kodowe z zakresu
U+10000
…U+10ffff
są kodowane jako para zastępcza, z których każdy jest reprezentowany jako 3-bajtowa zakodowana wartość. - Punkt kodowy
U+0000
jest zakodowany w formacie dwubajtowym. - Zwykły bajt zerowy (wartość
0
) oznacza koniec ciągu, zgodnie ze standardową interpretacją w języku C.
Pierwsze 2 punkty można podsumować w ten sposób: MUTF-8 to format kodowania UTF-16, a nie bardziej bezpośredni format kodowania znaków Unicode.
Dwa ostatnie elementy powyżej umożliwiają jednocześnie umieszczenie punktu kodowego U+0000
w ciągu znaków i manipulowanie nim jako ciągiem znaków zakończonym znakiem null w stylu C.
Specjalne kodowanie znaku U+0000
oznacza jednak, że w przeciwieństwie do zwykłego kodowania UTF-8 wynik wywołania standardowej funkcji języka C strcmp()
na parze ciągów MUTF-8 nie zawsze wskazuje prawidłowo podpisany wynik porównania nierównych ciągów.
Jeśli ważna jest kolejność (nie tylko równość), najprostszym sposobem porównania ciągów znaków MUTF-8 jest dekodowanie ich znak po znaku i porównywanie zdekodowanych wartości. (Możliwe są jednak bardziej zaawansowane implementacje).
Więcej informacji o kodowaniu znaków znajdziesz w standardzie Unicode. MUTF-8 jest w rzeczywistości bliższy (stosunkowo mniej znanemu) kodowaniu CESU-8 niż UTF-8.
kodowanie encoded_value
Umieszczony w elementach annotation_element i encoded_array_item
encoded_value
to zakodowany fragment (prawie) dowolnych danych o strukturze hierarchicznej. Kodowanie ma być zarówno kompaktowe, jak i łatwe do analizowania.
Nazwa | Format | Opis |
---|---|---|
(value_arg << 5) | value_type | ubyte | bajt wskazujący typ bezpośrednio następującego
value wraz
z opcjonalnym argumentem wyjaśniającym w 3 bitach wyższego rzędu.
Poniżej znajdziesz różne value definicje.
W większości przypadków value_arg koduje długość bezpośrednio następującego po nim pola value w bajtach, np.(size - 1) . 0 oznacza, że wartość wymaga 1 bajta, a 7 – 8 bajtów. Istnieją jednak wyjątki, o których piszemy poniżej.
|
wartość | ubyte[] | bajtów reprezentujących wartość o zmiennej długości, które są interpretowane
w różny sposób w zależności od bajtów value_type , ale zawsze w formacie little-endian. Szczegółowe informacje znajdziesz w definicjach różnych wartości poniżej.
|
Formaty wartości
Wpisz nazwę | value_type |
value_arg Format |
value Format |
Opis |
---|---|---|---|---|
VALUE_BYTE | 0x00 | (brak; musi być 0 ) |
ubyte[1] | 1-bajtowa liczba całkowita ze znakiem |
VALUE_SHORT | 0x02 | size - 1 (0…1) | ubyte[size] | dwubajtowa liczba całkowita ze znakiem, rozszerzona o znak; |
VALUE_CHAR | 0x03 | size - 1 (0…1) | ubyte[size] | wartość całkowita bez znaku o długości 2 bajtów, uzupełniona zerami; |
VALUE_INT | 0x04 | size - 1 (0…3) | ubyte[size] | wartość całkowita ze znakiem o długości 4 bajtów, rozszerzona o znak; |
VALUE_LONG | 0x06 | rozmiar – 1 (0–7) | ubyte[size] | ośmiobajtowa liczba całkowita ze znakiem, rozszerzona o znak; |
VALUE_FLOAT | 0x10 | size - 1 (0…3) | ubyte[size] | 4-bajtowy wzorzec bitowy, rozszerzony zerami po prawej stronie i interpretowany jako 32-bitowa wartość zmiennoprzecinkowa IEEE754. |
VALUE_DOUBLE | 0x11 | rozmiar – 1 (0–7) | ubyte[size] | 8-bajtowy wzorzec bitowy, uzupełniony zerami z prawej strony i interpretowany jako 64-bitowa wartość zmiennoprzecinkowa IEEE754. |
VALUE_METHOD_TYPE | 0x15 | size - 1 (0…3) | ubyte[size] | niepodpisana (rozszerzona do zera) 4-bajtowa wartość całkowita, interpretowana jako indeks w sekcji proto_ids i reprezentująca wartość typu metody.
|
VALUE_METHOD_HANDLE | 0x16 | size - 1 (0…3) | ubyte[size] | niepodpisana (rozszerzona do zera) 4-bajtowa wartość całkowita, interpretowana jako indeks w sekcji method_handles i reprezentująca wartość uchwytu metody;
|
VALUE_STRING | 0x17 | size - 1 (0…3) | ubyte[size] | niepodpisana (rozszerzona do zera) 4-bajtowa wartość całkowita, interpretowana jako indeks w sekcji string_ids i reprezentująca wartość ciągu znaków.
|
VALUE_TYPE | 0x18 | size - 1 (0…3) | ubyte[size] | niepodpisana (rozszerzona do zera) 4-bajtowa wartość całkowita, która jest interpretowana jako indeks w sekcji type_ids i reprezentuje wartość typu/klasy odbijającej;
|
VALUE_FIELD | 0x19 | size - 1 (0…3) | ubyte[size] | niepodpisana (rozszerzona do zera) 4-bajtowa liczba całkowita, interpretowana jako indeks w sekcji field_ids i reprezentująca wartość pola odblaskowego.
|
VALUE_METHOD | 0x1a | size - 1 (0…3) | ubyte[size] | niepodpisana (rozszerzona do zera) 4-bajtowa liczba całkowita, interpretowana jako indeks w sekcji method_ids i reprezentująca wartość metody refleksyjnej.
|
VALUE_ENUM | 0x1b | size - 1 (0…3) | ubyte[size] | niepodpisana (rozszerzona do zera) 4-bajtowa liczba całkowita, interpretowana jako indeks w sekcji field_ids i reprezentująca wartość stałej typu wyliczeniowego.
|
VALUE_ARRAY | 0x1c | (brak; musi być 0 ) |
encoded_array | tablicę wartości w formacie określonym poniżej w sekcji „encoded_array format”. Rozmiar value jest określony w kodowaniu.
|
VALUE_ANNOTATION | 0x1d | (brak; musi być 0 ) |
encoded_annotation | podrzędną adnotację w formacie określonym poniżej w sekcji „encoded_annotation format”. Rozmiar value jest określony w kodowaniu.
|
VALUE_NULL | 0x1e | (brak; musi być 0 ) |
(brak) | null wartość referencyjna |
VALUE_BOOLEAN | 0x1f | wartość logiczna (0–1) | (brak) | wartość 1-bitowa: 0 dla false i 1 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] | ciąg sekwencji bajtów size encoded_value 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 (nie tablicy ani typu prostego). |
rozmiar | uleb128 | liczba mapowań nazwa-wartość w tej adnotacji. |
elementów | annotation_element[size] | elementy adnotacji, które są reprezentowane bezpośrednio w tekście (nie jako przesunięcia). Elementy muszą być posortowane w kolejności rosnącej według string_id indeksu.
|
format annotation_element
Nazwa | Format | Opis |
---|---|---|
name_idx | uleb128 | nazwa elementu, reprezentowana jako indeks w sekcji string_ids . Ciąg znaków musi być zgodny ze składnią MemberName zdefiniowaną powyżej.
|
wartość | encoded_value | wartość elementu, |
Składnia ciągu tekstowego
W pliku .dex
jest kilka rodzajów elementów, które ostatecznie odnoszą się do ciągu znaków. Poniższe definicje w stylu BNF określają dopuszczalną składnię tych ciągów tekstowych.
SimpleName
SimpleName to podstawa składni nazw innych elementów. Format .dex
daje w tym przypadku sporą swobodę (znacznie większą niż większość popularnych języków źródłowych). Krótko mówiąc, prosta nazwa składa się z dowolnego znaku alfabetu lub cyfry z zakresu ASCII, kilku konkretnych symboli z zakresu ASCII oraz większości punktów kodowych spoza zakresu ASCII, które nie są znakami sterującymi, spacjami ani znakami specjalnymi. Od wersji 040
format dopuszcza też spacje (kategoria Unicode Zs
). Pamiętaj, że punkty kodowe zastępcze (w zakresie U+d800
–U+dfff
) nie są same w sobie uznawane za prawidłowe znaki w nazwie, ale dodatkowe znaki Unicode są prawidłowe (są one reprezentowane przez ostatnią alternatywę reguły SimpleNameChar) i powinny być reprezentowane w pliku jako pary zastępczych punktów kodowych w kodowaniu MUTF-8.
SimpleName → | ||
SimpleNameChar (SimpleNameChar)* | ||
SimpleNameChar → | ||
'A' … 'Z' |
||
| | 'a' … 'z' |
|
| | '0' … '9' |
|
| | ' ' |
od wersji DEX 040, |
| | '$' |
|
| | '-' |
|
| | '_' |
|
| | U+00a0 |
od wersji DEX 040, |
| | U+00a1 … U+1fff |
|
| | U+2000 … U+200a |
od wersji DEX 040, |
| | U+2010 … U+2027 |
|
| | U+202f |
od wersji DEX 040, |
| | U+2030 … U+d7ff |
|
| | U+e000 … U+ffef |
|
| | U+10000 … U+10ffff |
MemberName
używany przez field_id_item i method_id_item
MemberName to nazwa elementu klasy, przy czym elementami są pola, metody i klasy wewnętrzne.
MemberName → | |
SimpleName | |
| | '<' SimpleName '>' |
FullClassName
FullClassName to pełna nazwa klasy, która zawiera opcjonalny specyfikator pakietu, a po nim wymaganą nazwę.
FullClassName → | |
OptionalPackagePrefix SimpleName | |
OptionalPackagePrefix → | |
(SimpleName '/' )* |
TypeDescriptor
Używane przez type_id_item
TypeDescriptor to reprezentacja dowolnego typu, w tym typów prostych, klas, tablic i void
. Poniżej znajdziesz wyjaśnienie znaczenia poszczególnych wersji.
TypeDescriptor → | |
'V' |
|
| | FieldTypeDescriptor |
FieldTypeDescriptor → | |
NonArrayFieldTypeDescriptor | |
| | ('[' * 1…255)
NonArrayFieldTypeDescriptor |
NonArrayFieldTypeDescriptor→ | |
'Z' |
|
| | 'B' |
| | 'S' |
| | 'C' |
| | 'I' |
| | 'J' |
| | 'F' |
| | 'D' |
| | 'L' FullClassName ';' |
ShortyDescriptor
Używane przez proto_id_item
ShortyDescriptor to skrócona reprezentacja prototypu metody, w tym typów zwracanych i parametrów, z wyjątkiem tego, że nie ma rozróżnienia między różnymi typami odwołań (klasa lub tablica). 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 TypeDescriptor
Oto znaczenie poszczególnych wariantów elementu 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 |
Lfully/qualified/Name; | zajęcia fully.qualified.Name |
[descriptor | tablica descriptor , której można używać rekursywnie 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ą pojawić się 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 | wartość magiczną. Więcej informacji znajdziesz w sekcji „DEX_FILE_MAGIC ” powyżej.
|
suma kontrolna | uint | Suma kontrolna adler32 pozostałej części pliku (wszystko oprócz magic i tego pola); służy do wykrywania uszkodzenia pliku.
|
podpis | ubyte[20] | Podpis SHA-1 (skrót) pozostałej części pliku (wszystko oprócz
magic , checksum i tego pola); służy do jednoznacznej identyfikacji plików.
|
file_size | uint |
rozmiar całego pliku (wraz z nagłówkiem) w bajtach(wersja 40 lub starsza) odległość w bajtach od początku tego nagłówka do następnego nagłówka lub do końca całego pliku (kontenera). (wersja 41 lub nowsza) |
header_size | uint |
rozmiar nagłówka (całej tej sekcji) w bajtach. Zapewnia to przynajmniej ograniczoną zgodność wsteczną i w przód bez unieważniania formatu. musi mieć 112 bajtów (0x70)(wersja 40 lub starsza) musi mieć 120 bajtów (0x78) (wersja 41 lub nowsza) |
endian_tag | uint = ENDIAN_CONSTANT | tag kolejności bajtów. Więcej informacji znajdziesz w omówieniu powyżej w sekcji „ENDIAN_CONSTANT i REVERSE_ENDIAN_CONSTANT ”.
|
link_size | uint | rozmiar sekcji linków lub 0 , jeśli ten plik nie jest statycznie połączony. |
link_off | uint | przesunięcie od początku pliku do sekcji linku lub0 jeśli link_size == 0 . Jeśli przesunięcie jest różne od zera, powinno wskazywać przesunięcie w sekcji link_data . Format danych, na które wskazuje ten nagłówek, nie jest określony w tym dokumencie. Ten nagłówek (i poprzedni) pozostawiono jako punkty zaczepienia do wykorzystania przez implementacje środowiska wykonawczego.
|
map_off | uint | przesunięcie od początku pliku do elementu mapy. Przesunięcie, które musi być niezerowe, powinno być przesunięciem do sekcji data , a dane powinny być w formacie określonym poniżej w sekcji „map_list ”.
|
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ągów znaków lub0 , jeśli string_ids_size == 0 (przyznaję, że to dziwny przypadek skrajny). Przesunięcie, jeśli jest różne od zera, powinno być względem początku sekcji string_ids .
|
type_ids_size | uint | liczba elementów na liście identyfikatorów typów, 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 (przyznaję, że to dziwny przypadek brzegowy). Przesunięcie, jeśli jest różne od zera, powinno być względem początku sekcji type_ids .
|
proto_ids_size | uint | liczba elementów na liście identyfikatorów prototypów, maksymalnie 65535 |
proto_ids_off | uint | przesunięcie od początku pliku do listy identyfikatorów prototypów lub 0 , jeśli proto_ids_size == 0 (przyznaję, że to dziwny przypadek skrajny). Przesunięcie, jeśli jest różne od zera, powinno być względem 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 . Przesunięcie, jeśli jest niezerowe, powinno być względem początku sekcji field_ids . |
method_ids_size | uint | liczba elementów na liście identyfikatorów metod. |
method_ids_off | uint | przesunięcie od początku pliku do listy identyfikatorów metod lub
0 , jeśli method_ids_size == 0 . Przesunięcie, jeśli jest niezerowe, powinno być względem 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 (przyznaję, że to dziwny przypadek brzegowy). Przesunięcie, jeśli jest różne od zera, powinno być względem początku sekcji class_defs .
|
data_size | uint |
Rozmiar sekcji Nieużywane (wersja 41 lub nowsza) |
data_off | uint |
przesunięcie od początku pliku do początku sekcji Nieużywane (wersja 41 lub nowsza) |
container_size | uint |
to pole nie istnieje. Można założyć, że jest równa rozmiar całego pliku (wraz z innymi nagłówkami dex i ich danymi); (wersja 41 lub nowsza) |
header_offset | uint |
to pole nie istnieje. Można założyć, że jest równa przesunięcie od początku pliku do początku tego nagłówka. (wersja 41 lub nowsza) |
map_list
Występuje w sekcji danych
Odniesienie z header_item
Wyrównanie: 4 bajty
Jest to lista całej zawartości pliku w odpowiedniej kolejności. Zawiera pewne powtórzenia w stosunku do header_item
, ale ma być łatwym w użyciu formularzem do iteracji po całym pliku. Dany typ może wystąpić w mapie co najwyżej raz, ale nie ma ograniczeń co do kolejności, w jakiej mogą się pojawiać typy, z wyjątkiem ograniczeń wynikających z pozostałej części formatu (np. sekcja header
musi pojawić się jako pierwsza, a po niej sekcja string_ids
itp.). Dodatkowo wpisy na mapie muszą być uporządkowane według początkowego przesunięcia i nie mogą się nakładać.
Nazwa | Format | Opis |
---|---|---|
rozmiar | uint | rozmiar listy (w postaci liczby wpisów), |
lista | map_item[size] | elementy listy, |
map_item format
Nazwa | Format | Opis |
---|---|---|
typ | ushort | rodzaj produktów (patrz tabela poniżej); |
unused | ushort | (nieużywane) |
rozmiar | uint | liczba elementów, które mają się znajdować w wskazanym przesunięciu. |
przesunięcie, | uint | przesunięcie od początku pliku do elementów, których dotyczy problem; |
Kody typów
Typ produktu | 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 | domyślny; musi być przeanalizowany |
code_item | TYPE_CODE_ITEM | 0x2001 | domyślny; musi być przeanalizowany |
string_data_item | TYPE_STRING_DATA_ITEM | 0x2002 | domyślny; musi być przeanalizowany |
debug_info_item | TYPE_DEBUG_INFO_ITEM | 0x2003 | domyślny; musi być przeanalizowany |
annotation_item | TYPE_ANNOTATION_ITEM | 0x2004 | domyślny; musi być przeanalizowany |
encoded_array_item | TYPE_ENCODED_ARRAY_ITEM | 0x2005 | domyślny; musi być przeanalizowany |
annotations_directory_item | TYPE_ANNOTATIONS_DIRECTORY_ITEM | 0x2006 | domyślny; musi być przeanalizowany |
hiddenapi_class_data_item | TYPE_HIDDENAPI_CLASS_DATA_ITEM | 0xF000 | domyślny; musi być przeanalizowany |
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 dla tego elementu. Przesunięcie powinno odnosić się do lokalizacji w sekcji data , a dane powinny mieć format określony poniżej w sekcji „string_data_item ”.
Przesunięcie nie musi być wyrównane.
|
string_data_item
Występuje w sekcji danych
Wyrównanie: brak (wyrównanie do bajtu)
Nazwa | Format | Opis |
---|---|---|
utf16_size | uleb128 | rozmiar tego ciągu znaków w jednostkach kodu UTF-16 (w wielu systemach jest to „długość ciągu znaków”). Jest to zdekodowana długość ciągu. (Zakodowana długość jest określana przez pozycję bajtu 0 ). |
dane | ubyte[] | ciąg jednostek kodu MUTF-8 (czyli oktetów lub bajtów)
zakończony bajtem o wartości 0 . Szczegółowe informacje i omówienie formatu danych znajdziesz w sekcji „Kodowanie MUTF-8 (zmodyfikowane UTF-8)” powyżej.
Uwaga: dopuszczalne jest użycie ciągu znaków, który zawiera (zakodowane) jednostki kodu zastępczego UTF-16 (czyli |
type_id_item
Występuje w sekcji type_ids
Wyrównanie: 4 bajty
Nazwa | Format | Opis |
---|---|---|
descriptor_idx | uint | indeks w string_ids liście ciągu znaków deskryptora tego typu. Ciąg znaków musi być zgodny ze składnią TypeDescriptor zdefiniowaną powyżej.
|
proto_id_item
Wyświetla się w sekcji proto_ids
Wyrównanie: 4 bajty
Nazwa | Format | Opis |
---|---|---|
shorty_idx | uint | indeks w string_ids dla krótkiego ciągu znaków opisującego ten prototyp. Ciąg znaków musi być zgodny ze składnią ShortyDescriptor zdefiniowaną powyżej i odpowiadać typowi zwracanych danych oraz parametrom tego elementu.
|
return_type_idx | uint | indeks w type_ids dla typu zwracanego tego prototypu
|
parameters_off | uint | przesunięcie od początku pliku do listy typów parametrów
dla tego prototypu lub 0 , jeśli ten prototyp nie ma
parametrów. Jeśli ten przesunięcie jest różne od zera, powinno znajdować się w sekcji data , a dane w niej powinny mieć format określony przez "type_list" poniżej. Poza tym na liście nie powinno być odwołania do typu void .
|
field_id_item
Pojawia się w sekcji field_ids
Wyrównanie: 4 bajty
Nazwa | Format | Opis |
---|---|---|
class_idx | ushort | indeks na liście type_ids dla definicji tego pola. Musi to być typ klasy, a nie tablica ani typ prosty.
|
type_idx | ushort | indeks na liście type_ids dla typu tego pola.
|
name_idx | uint | indeks do listy string_ids dla nazwy tego pola. Ciąg znaków musi być zgodny ze składnią MemberName zdefiniowaną powyżej.
|
method_id_item
Wyświetla się 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 prosty.
|
proto_idx | ushort | indeks na liście proto_ids dla prototypu tej metody
|
name_idx | uint | indeks w string_ids liście nazwy tej metody. Ciąg znaków musi być zgodny ze składnią MemberName zdefiniowaną 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 tych zajęć.
Musi to być typ klasy, a nie tablica ani typ prosty.
|
access_flags | uint | flagi dostępu do klasy (public , final itp.); Więcej informacji znajdziesz w sekcji „access_flags Definicje”.
|
superclass_idx | uint | indeks na liście type_ids dla klasy nadrzędnej lub stała NO_INDEX , jeśli ta klasa nie ma klasy nadrzędnej (czyli jest klasą główną, np. Object ). Jeśli ten element jest obecny, musi to być typ klasy, a nie tablica ani typ prosty.
|
interfaces_off | uint | przesunięcie od początku pliku do listy interfejsów lub
0 , jeśli nie ma żadnych interfejsów. Ten przesunięcie
powinno znajdować się w sekcji data , a dane
w niej powinny mieć format określony
poniżej w sekcji „type_list ”. Każdy element listy musi być typem klasy (nie może być tablicą ani typem prostym) i nie może zawierać duplikatów.
|
source_file_idx | uint | indeks na liście string_ids dla nazwy pliku zawierającego oryginalne źródło (przynajmniej większości) tej klasy lub wartość specjalną NO_INDEX , która oznacza brak tych informacji. debug_info_item dowolnej metody może zastąpić ten plik źródłowy, ale oczekuje 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 tej klasy lub 0 , jeśli w tej klasie nie ma adnotacji. Jeśli ten przesunięcie jest różne od zera, powinno znajdować się w sekcji data , a dane w tej sekcji powinny mieć format określony poniżej przez „annotations_directory_item ”, przy czym wszystkie elementy odwołujące się do tej klasy powinny być definiowane przez nią.
|
class_data_off | uint | przesunięcie od początku pliku do powiązanych danych zajęć dla tego elementu lub 0 , jeśli nie ma danych zajęć dla tych zajęć. (Może to mieć miejsce np. w przypadku, gdy ta klasa jest interfejsem znacznika). Jeśli przesunięcie jest różne od zera, powinno znajdować się w sekcji data , a dane w tej sekcji powinny mieć format określony przez „class_data_item ” poniżej. Wszystkie elementy powinny odwoływać się do tej klasy jako definicji.
|
static_values_off | uint | przesunięcie od początku pliku do listy wartości początkowych pól static lub 0 , jeśli nie ma żadnych pól (a wszystkie pola static mają być inicjowane wartością 0 lub null ). To przesunięcie powinno znajdować się w sekcji data , a dane w niej powinny mieć format określony poniżej w sekcji „encoded_array_item ”. 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 field_list . Typ każdego elementu tablicy musi być zgodny z zadeklarowanym typem odpowiedniego pola.
Jeśli w tablicy jest mniej elementów niż pól static , pozostałe pola są inicjowane odpowiednim typem 0 lub null .
|
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 miejsca wywołania. Przesunięcie powinno znajdować się w sekcji danych, a dane w niej powinny mieć format określony w sekcji „call_site_item” poniżej. |
call_site_item
Występuje w sekcji danych
Wyrównanie: brak (wyrównanie do bajtu)
call_site_item to encoded_array_item, którego elementy odpowiadają argumentom przekazanym do metody linkera bootstrap. Pierwsze 3 argumenty to:
- Uchwyt metody reprezentujący metodę linkera bootstrap (VALUE_METHOD_HANDLE).
- Nazwa metody, którą powinien rozwiązać linker bootstrap (VALUE_STRING).
- Typ metody odpowiadający typowi nazwy metody do rozwiązania (VALUE_METHOD_TYPE).
Wszystkie dodatkowe argumenty to stałe wartości przekazywane do metody linkera bootstrap. Argumenty te są przekazywane w kolejności i bez konwersji typów.
Uchwyt metody reprezentujący metodę linkera bootstrap musi mieć typ zwracany java.lang.invoke.CallSite
. Pierwsze 3 typy parametrów to:
java.lang.invoke.Lookup
java.lang.String
java.lang.invoke.MethodType
Typy parametrów dodatkowych argumentów są określane na podstawie ich stałych wartości.
method_handle_item
Pojawia się 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żywane) |
field_or_method_id | ushort | Identyfikator pola lub metody w zależności od tego, czy typ uchwytu metody jest akcesorem czy wywołującym metodę. |
unused | ushort | (nieużywane) |
Kody typów uchwytów metod
Stała | Wartość | Opis |
---|---|---|
METHOD_HANDLE_TYPE_STATIC_PUT | 0x00 | Uchwyt metody jest ustawiającym pole statyczne (akcesorem) |
METHOD_HANDLE_TYPE_STATIC_GET | 0x01 | Uchwyt metody jest statycznym pobieraniem pola (akcesorem) |
METHOD_HANDLE_TYPE_INSTANCE_PUT | 0x02 | Uchwyt metody jest ustawiającym pole instancji (akcesorem) |
METHOD_HANDLE_TYPE_INSTANCE_GET | 0x03 | Uchwyt metody jest getterem pola instancji (akcesorem) |
METHOD_HANDLE_TYPE_INVOKE_STATIC | 0x04 | Uchwyt metody to wywołujący metodę statyczną |
METHOD_HANDLE_TYPE_INVOKE_INSTANCE | 0x05 | Uchwyt metody to wywołujący metodę instancji |
METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR | 0x06 | Uchwyt metody to wywołujący metodę konstruktora. |
METHOD_HANDLE_TYPE_INVOKE_DIRECT | 0x07 | Uchwyt metody to bezpośredni wywołujący metodę |
METHOD_HANDLE_TYPE_INVOKE_INTERFACE | 0x08 | Uchwyt metody jest wywołaniem metody interfejsu |
class_data_item
Odniesienie do elementu class_def_item
Występuje w sekcji danych
Wyrównanie: brak (wyrównanie do bajtu)
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 (dowolne z static , private lub konstruktor), 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 (żadna z metod static , private ani konstruktor), reprezentowane jako sekwencja zakodowanych elementów. Ta lista nie powinna zawierać metod dziedziczonych, chyba że zostały one zastąpione przez klasę, którą reprezentuje ten element. Metody muszą być posortowane według kolumny method_idx w kolejności rosnącej.
method_idx metody wirtualnej musi nie być taka sama jak w przypadku żadnej metody bezpośredniej.
|
Uwaga: wszystkie instancje 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 w field_ids liście tożsamości tego pola (zawiera nazwę i opis), reprezentowany jako różnica w stosunku do 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 itp.). Więcej informacji znajdziesz w sekcji „access_flags Definicje”.
|
Format encoded_method
Nazwa | Format | Opis |
---|---|---|
method_idx_diff | uleb128 | indeks w method_ids liście tożsamości tej metody (zawiera nazwę i opis), reprezentowany jako różnica od indeksu poprzedniego elementu na liście. Indeks pierwszego elementu na liście jest reprezentowany bezpośrednio.
|
access_flags | uleb128 | flagi dostępu do metody (public , final itp.). 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 ma wartość abstract lub native . Przesunięcie powinno odnosić się do lokalizacji w sekcji data . Format danych jest określony przez „code_item ” poniżej.
|
type_list
Przywoływana przez class_def_item i proto_id_item
Występuje w sekcji danych
Wyrównanie: 4 bajty
Nazwa | Format | Opis |
---|---|---|
rozmiar | uint | rozmiar listy (w postaci liczby wpisów), |
lista | type_item[size] | elementy listy, |
type_item format
Nazwa | Format | Opis |
---|---|---|
type_idx | ushort | indeks na liście type_ids |
code_item
Przywoływana z pola 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 wychodzącej przestrzeni argumentów wymaganej przez ten kod do wywołania metody. |
tries_size | ushort | liczba try_item w tej instancji. Jeśli wartość jest różna od zera, pojawiają się one jako tablica tries tuż po insns w tym przypadku.
|
debug_info_off | uint | przesunięcie od początku pliku do sekwencji informacji debugowania (numery wierszy + informacje o zmiennych lokalnych) dla tego kodu lub 0 , jeśli nie ma żadnych informacji. Jeśli przesunięcie jest różne od zera, powinno odnosić się do lokalizacji w sekcji data . Format danych jest określony przez „debug_info_item ” poniżej.
|
insns_size | uint | rozmiar listy instrukcji w 16-bitowych jednostkach kodu, |
insns | ushort[insns_size] | rzeczywistą tablicę kodu bajtowego. Format kodu w insns tablicy jest określony w dokumencie towarzyszącym Dalvik bytecode. Pamiętaj, że choć jest to zdefiniowane jako tablica ushort , niektóre struktury wewnętrzne preferują wyrównanie do 4 bajtów. Jeśli plik jest zapisany w formacie z odwróconą kolejnością bajtów, odwrócenie kolejności bajtów jest wykonywane tylko w przypadku poszczególnych ushort wystąpień, a nie w przypadku większych struktur wewnętrznych.
|
padding | ushort (optional) = 0 | 2 bajty dopełnienia, aby wyrównać tries do 4 bajtów.
Ten element jest obecny tylko wtedy, gdy tries_size jest liczbą różną od zera, a insns_size jest liczbą nieparzystą.
|
próbuje | try_item[tries_size] (opcjonalny) | tablica wskazująca, gdzie w kodzie są przechwytywane wyjątki i jak je obsługiwać. Elementy tablicy nie mogą się pokrywać w zakresie i muszą być uporządkowane od najniższego do najwyższego adresu. Ten element występuje tylko wtedy, gdy wartość tries_size jest różna od zera.
|
moduły obsługi | encoded_catch_handler_list (opcjonalnie) | bajtów reprezentujących listę list typów przechwytywania i powiązanych adresów
procedur obsługi. Każdy try_item ma przesunięcie w bajtach
w tej strukturze. Ten element jest obecny tylko wtedy, gdy wartość tries_size jest różna od zera.
|
Format try_item
Nazwa | Format | Opis |
---|---|---|
start_addr | uint | adres początkowy bloku kodu objętego tym wpisem. Adres to liczba 16-bitowych jednostek kodu do początku pierwszej objętej instrukcji. |
insn_count | ushort | liczba 16-bitowych jednostek kodu objętych tym wpisem. Ostatnia jednostka kodu (włącznie) to start_addr + insn_count - 1 .
|
handler_off | ushort | przesunięcie w bajtach od początku powiązanego
encoded_catch_hander_list do
encoded_catch_handler w przypadku tego wpisu. Musi to być przesunięcie względem początku encoded_catch_handler .
|
encoded_catch_handler_list
Nazwa | Format | Opis |
---|---|---|
rozmiar | uleb128 | rozmiar tej listy (w liczbie wpisów); |
lista | encoded_catch_handler[handlers_size] | rzeczywista lista list obsługi, reprezentowana bezpośrednio (nie jako przesunięcia) i połączona sekwencyjnie. |
Format encoded_catch_handler
Nazwa | Format | Opis |
---|---|---|
rozmiar | sleb128 | liczba typów połowów na tej liście. Jeśli jest to liczba nie dodatnia, jest to liczba przeciwna do liczby typów klauzul catch, a po klauzulach catch następuje ogólna obsługa błędów. Na przykład size o wartości 0 oznacza, że istnieje reguła ogólna, ale nie ma reguł z określonym typem.
Wartość size w przypadku 2 oznacza, że istnieją 2 jawnie określone reguły przechwytywania i nie ma reguły ogólnej. A size -1 oznacza, że jest jeden typowany warunek wraz z warunkiem ogólnym.
|
moduły obsługi | encoded_type_addr_pair[abs(size)] | strumień zakodowanych elementów abs(size) , po jednym dla każdego przechwyconego typu, w kolejności, w jakiej typy powinny być testowane.
|
catch_all_addr | uleb128 (opcjonalnie) | adres kodu bajtowego obsługi catch-all. Ten element występuje tylko wtedy, gdy wartość size jest nie większa niż 0.
|
Format encoded_type_addr_pair
Nazwa | Format | Opis |
---|---|---|
type_idx | uleb128 | indeks na type_ids liście typu wyjątku do przechwycenia.
|
addr | uleb128 | adres kodu bajtowego powiązanego modułu obsługi wyjątków, |
debug_info_item
Odniesienie z code_item
Występuje w sekcji danych
Wyrównanie: brak (wyrównanie do bajtu)
Każdy element debug_info_item
definiuje automat stanowy zakodowany w postaci bajtów, inspirowany formatem DWARF3. Po zinterpretowaniu generuje on tabelę pozycji i (potencjalnie) informacje o zmiennych lokalnych dla elementu code_item
. Sekwencja zaczyna się od nagłówka o zmiennej długości (która zależy od liczby parametrów metody), po którym następują kody bajtowe automatu stanowego, a kończy się bajtem DBG_END_SEQUENCE
.
Automat 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 0
na początku każdej sekwencji debug_info
i musi tylko rosnąć monotonicznie.
Rejestr line
reprezentuje numer wiersza źródłowego, który powinien być powiązany z następnym wpisem w tabeli pozycji wygenerowanym przez automat stanowy. Jest ona inicjowana w nagłówku sekwencji i może zmieniać się w kierunku dodatnim lub ujemnym, ale nigdy nie może być mniejsza niż 1
. Rejestr source_file
reprezentuje plik źródłowy, do którego odnoszą się wpisy numerów wierszy. Jest on inicjowany wartością source_file_idx
w class_def_item
.
Pozostałe 2 zmienne, prologue_end
i epilogue_begin
, to flagi wartości logicznej (inicjowane jako false
), które wskazują, czy następna emitowana pozycja powinna być traktowana jako prolog lub epilog metody. Automat stanowy musi też śledzić nazwę i typ ostatniej zmiennej lokalnej, która jest aktywna w każdym rejestrze dla kodu DBG_RESTART_LOCAL
.
Nagłówek wygląda tak:
Nazwa | Format | Opis |
---|---|---|
line_start | uleb128 | wartość początkowa rejestru line automatu stanowego.
Nie reprezentuje rzeczywistego wpisu dotyczącego stanowiska.
|
parameters_size | uleb128 | liczba zakodowanych nazw parametrów. Powinien być jeden dla każdego parametru metody, z wyjątkiem parametru this metody instancji, jeśli taki istnieje.
|
parameter_names | uleb128p1[parameters_size] | indeks ciągu znaków nazwy parametru metody. Zakodowana wartość NO_INDEX oznacza, że dla powiązanego parametru nie jest dostępna żadna nazwa. Deskryptor typu
i podpis są implikowane przez deskryptor metody i podpis.
|
Wartości kodu bajtowego są następujące:
Nazwa | Wartość | Format | Argumenty | Opis |
---|---|---|---|---|
DBG_END_SEQUENCE | 0x00 | (brak) | kończy sekwencję informacji debugowania dla code_item . |
|
DBG_ADVANCE_PC | 0x01 | uleb128 addr_diff | addr_diff : kwota do dodania do rejestru adresów |
przesuwa rejestr adresów bez emitowania wpisu pozycji; |
DBG_ADVANCE_LINE | 0x02 | sleb128 line_diff | line_diff : kwota, o którą należy zmienić rejestr wiersza. |
przesuwa rejestr wierszy bez emitowania wpisu pozycji; |
DBG_START_LOCAL | 0x03 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx |
register_num : rejestr, który będzie zawierać lokalnyname_idx : indeks ciągu nazwytype_idx : indeks typu
|
wprowadza zmienną lokalną pod bieżącym adresem. Wartość name_idx lub type_idx może być NO_INDEX , aby wskazać, że wartość jest nieznana.
|
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ć lokalnyname_idx : indeks ciągu nazwytype_idx : indeks typusig_idx : indeks ciągu sygnatury typu
|
wprowadza zmienną lokalną o sygnaturze typu pod bieżącym adresem.
Wartość name_idx , type_idx lub sig_idx może być NO_INDEX , aby wskazać, że ta wartość jest nieznana. (Jeśli jednak sig_idx jest mniejsze niż -1 , te same dane można przedstawić wydajniej za pomocą kodu operacji DBG_START_LOCAL ).
Uwaga: uwagi dotyczące obsługi podpisów znajdziesz w sekcji „ |
DBG_END_LOCAL | 0x05 | uleb128 register_num | register_num : register that contained local |
oznacza bieżącą zmienną lokalną jako wykraczającą poza zakres w bieżącym adresie. |
DBG_RESTART_LOCAL | 0x06 | uleb128 register_num | register_num : zarejestruj się, aby ponownie uruchomić |
ponownie wprowadza zmienną lokalną pod bieżącym adresem. Nazwa i typ są takie same jak w przypadku ostatniego lokalnego, który był aktywny w określonym rejestrze. |
DBG_SET_PROLOGUE_END | 0x07 | (brak) | ustawia rejestr maszyny stanowej prologue_end , co oznacza, że następny dodany wpis pozycji powinien być traktowany jako koniec prologu metody (odpowiednie miejsce na punkt przerwania metody). Rejestr prologue_end jest czyszczony przez dowolny specjalny kod operacji (>= 0x0a ).
|
|
DBG_SET_EPILOGUE_BEGIN | 0x08 | (brak) | ustawia epilogue_begin rejestr maszyny stanowej, co oznacza, że następny dodany wpis pozycji powinien być traktowany jako początek epilogu metody (odpowiednie miejsce do wstrzymania wykonania przed zakończeniem metody).
Rejestr epilogue_begin jest czyszczony przez dowolny specjalny kod operacji (>= 0x0a ).
|
|
DBG_SET_FILE | 0x09 | uleb128p1 name_idx | name_idx : indeks ciągu nazwy pliku źródłowego;
NO_INDEX jeśli nieznany
|
oznacza, że wszystkie kolejne wpisy numerów wierszy odnoszą się do tej nazwy pliku źródłowego, a nie do nazwy domyślnej określonej w code_item .
|
Specjalne kody operacji | 0x0a…0xff | (brak) | zwiększa wartości rejestrów line i address ,
wysyła wpis pozycji i czyści rejestry prologue_end i epilogue_begin . Opis znajdziesz poniżej.
|
Specjalne kody operacji
Kody operacji o wartościach z zakresu od 0x0a
do 0xff
(włącznie) przesuwają rejestry line
i address
o niewielką wartość, a następnie emitują nowy wpis w tabeli pozycji.
Wzory na przyrosty są następujące:
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
Odniesienie do elementu 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 ma bezpośrednich adnotacji.
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.
|
fields_size | uint | liczba pól oznaczonych tym elementem. |
annotated_methods_size | uint | liczba metod oznaczonych adnotacją przez ten element, |
annotated_parameters_size | uint | liczba list parametrów metod oznaczonych adnotacjami przez ten element. |
field_annotations | field_annotation[fields_size] (opcjonalny) | lista powiązanych adnotacji pól. Elementy listy muszą być posortowane w kolejności rosnącej według parametru field_idx .
|
method_annotations | method_annotation[methods_size] (opcjonalny) | lista powiązanych adnotacji metod. Elementy listy muszą być posortowane w kolejności rosnącej według parametru method_idx .
|
parameter_annotations | parameter_annotation[parameters_size] (opcjonalny) | lista powiązanych adnotacji parametrów metody. Elementy listy muszą być posortowane w kolejności rosnącej według parametru method_idx .
|
Uwaga: wszystkie instancje 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 dla tożsamości pola, które jest oznaczane;
|
annotations_off | uint | przesunięcie od początku pliku do listy adnotacji dotyczących pola. Przesunięcie powinno odnosić się do lokalizacji 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 method_ids na potrzeby tożsamości metody, która jest opatrywana adnotacjami.
|
annotations_off | uint | przesunięcie od początku pliku do listy adnotacji dla metody. Przesunięcie powinno odnosić się do 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 na liście method_ids , który określa tożsamość metody, której parametry są oznaczane;
|
annotations_off | uint | przesunięcie od początku pliku do listy adnotacji dla parametrów metody. Przesunięcie powinno odnosić się do lokalizacji w sekcji data . Format danych jest określony przez „annotation_set_ref_list ” poniżej.
|
annotation_set_ref_list
Odwołanie z parametru parameter_annotations_item
Występuje w sekcji danych
Wyrównanie: 4 bajty
Nazwa | Format | Opis |
---|---|---|
rozmiar | uint | rozmiar listy (w postaci liczby wpisów), |
lista | annotation_set_ref_item[size] | elementy listy, |
annotation_set_ref_item format
Nazwa | Format | Opis |
---|---|---|
annotations_off | uint | przesunięcie od początku pliku do odwołującego się do niego zbioru adnotacji
lub 0 , jeśli dla tego elementu nie ma adnotacji.
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
Przywoływana z 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 (w liczbie wpisów); |
wpisy, | annotation_off_item[size] | elementy zbioru. 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.
Przesunięcie powinno wskazywać lokalizację w sekcji data , a format danych w tej lokalizacji jest określony przez „annotation_item ” poniżej.
|
annotation_item
Przywoływana z elementu annotation_set_item
Występuje w sekcji danych
Wyrównanie: brak (wyrównanie do bajtu)
Nazwa | Format | Opis |
---|---|---|
widoczność | ubyte | zamierzona widoczność tej adnotacji (patrz poniżej); |
adnotacja | encoded_annotation | zakodowane treści adnotacji w formacie opisanym w sekcji „encoded_annotation format” w części „encoded_value encoding” powyżej.
|
Wartości widoczności
Opcje pola visibility
w annotation_item
:
Nazwa | Wartość | Opis |
---|---|---|
VISIBILITY_BUILD | 0x00 | mają być widoczne tylko w czasie kompilacji (np. podczas kompilowania innego kodu); |
VISIBILITY_RUNTIME | 0x01 | przeznaczony do wyświetlania w czasie działania |
VISIBILITY_SYSTEM | 0x02 | przeznaczone do wyświetlania w czasie działania, ale tylko w systemie bazowym (a nie w zwykłym kodzie użytkownika). |
encoded_array_item
Odniesienie do elementu class_def_item
Występuje w sekcji danych
Wyrównanie: brak (wyrównanie do bajtu)
Nazwa | Format | Opis |
---|---|---|
wartość | encoded_array | bajty reprezentujące zakodowaną wartość tablicy w formacie określonym w sekcji „encoded_array Format” w części „encoded_value
Kodowanie” powyżej.
|
hiddenapi_class_data_item
Ta sekcja zawiera dane o ograniczonych interfejsach używanych przez każdą klasę.
Uwaga: ukryta funkcja interfejsu API została wprowadzona w Androidzie 10.0 i ma zastosowanie tylko do plików DEX klas w ścieżce klasy rozruchowej. Lista flag opisanych poniżej może zostać rozszerzona w przyszłych wersjach Androida. Więcej informacji znajdziesz w artykule o ograniczeniach dotyczących interfejsów innych niż SDK.
Nazwa | Format | Opis |
---|---|---|
rozmiar | uint | całkowity rozmiar sekcji, |
offsets | uint[] | tablica przesunięć indeksowana przez class_idx .
Wpis zerowy w tablicy na pozycji class_idx oznacza, że albo nie ma danych dla tego class_idx , albo wszystkie ukryte flagi interfejsu API mają wartość zero.
W przeciwnym razie wpis w tablicy jest różny od zera i zawiera przesunięcie od początku sekcji do tablicy ukrytych flag interfejsu API dla tego class_idx .
|
flagi, | uleb128[] | połą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 co pola, a metody są kodowane w danych klasy. |
Typy flag ograniczeń:
Nazwa | Wartość | Opis |
---|---|---|
biała lista, | 0 | Interfejsy, z których można swobodnie korzystać i które są obsługiwane w ramach oficjalnie udokumentowanego frameworka Androida – indeks pakietów. |
szara lista | 1 | Interfejsy spoza SDK, których można używać niezależnie od docelowego poziomu interfejsu API aplikacji. |
zablokuj | 2 | Interfejsy spoza SDK, których nie można używać niezależnie od docelowego poziomu interfejsu API aplikacji. Dostęp do jednego z tych interfejsów powoduje błąd podczas działania. |
greylist‑max‑o | 3 | Interfejsy spoza SDK, których można używać w Androidzie 8.x i starszych wersjach, chyba że są objęte ograniczeniami. |
greylist‑max‑p | 4 | Interfejsy inne niż SDK, których można używać w Androidzie 9.x, chyba że są ograniczone. |
greylist‑max‑q | 5 | Interfejsy spoza SDK, których można używać w Androidzie 10.x, o ile nie są objęte ograniczeniami. |
greylist‑max‑r | 6 | Interfejsy spoza SDK, których można używać w Androidzie 11.x, chyba że są objęte ograniczeniami. |
Adnotacje systemowe
Adnotacje systemowe służą do reprezentowania różnych informacji o klasach (oraz metodach i polach). Dostęp do tych informacji jest zwykle uzyskiwany pośrednio przez kod klienta (inny niż systemowy).
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 powiązania, dołączona jest adnotacja AnnotationDefault
.
Nazwa | Format | Opis |
---|---|---|
wartość | Adnotacja | domyślne powiązania dla 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
Wyświetlanie na zajęciach
Do każdej klasy dołączona jest adnotacja EnclosingClass
, która jest zdefiniowana jako element innej klasy lub jest anonimowa, ale nie jest zdefiniowana w treści metody (np. syntetyczna klasa wewnętrzna). Każda klasa, która ma tę adnotację, musi mieć też adnotację
InnerClass
. Klasa nie może mieć jednocześnie adnotacji EnclosingClass
i EnclosingMethod
.
Nazwa | Format | Opis |
---|---|---|
wartość | Kategoria | klasa, która jest najbliższa tej klasie pod względem leksykalnym; |
dalvik.annotation.EnclosingMethod
Wyświetlanie na zajęciach
Do każdej klasy zdefiniowanej w treści metody dołączona jest adnotacja EnclosingMethod
. Każda klasa, która ma tę adnotację, musi mieć też adnotację InnerClass
.
Dodatkowo klasa nie może 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
Wyświetlanie na zajęciach
Do każdej klasy InnerClass
zdefiniowanej w zakresie leksykalnym definicji innej klasy jest dołączona adnotacja.
Każda klasa, która ma tę adnotację, musi mieć też adnotację EnclosingClass
lub EnclosingMethod
.
Nazwa | Format | Opis |
---|---|---|
nazwa | Ciąg znaków | pierwotnie zadeklarowana prosta nazwa tej klasy (bez prefiksu pakietu). Jeśli zajęcia są anonimowe, nazwa to null .
|
accessFlags | int | pierwotnie zadeklarowane flagi dostępu klasy (które mogą się różnić od flag efektywnych z powodu niezgodności między modelami wykonania języka źródłowego a docelowej maszyny wirtualnej); |
dalvik.annotation.MemberClasses
Wyświetlanie na zajęciach
Do każdej klasy, która deklaruje klasy składowe, dołączona jest adnotacja MemberClasses
. (Klasa składowa to bezpośrednia klasa wewnętrzna, która ma nazwę).
Nazwa | Format | Opis |
---|---|---|
wartość | Klasa[] | tablica klas elementów |
dalvik.annotation.MethodParameters
Pojawia się w metodach
Uwaga: ta adnotacja została dodana po Androidzie 7.1. W starszych wersjach Androida będzie on ignorowany.
Adnotacja MethodParameters
jest opcjonalna i może służyć do podawania metadanych parametrów, takich jak nazwy parametrów i modyfikatory.
Adnotację można bezpiecznie pominąć w metodzie lub konstruktorze, gdy metadane parametru nie są wymagane w czasie działania.
java.lang.reflect.Parameter.isNamePresent()
można użyć do sprawdzenia, czy dla parametru są dostępne metadane, a powiązane metody odbicia, takie jak java.lang.reflect.Parameter.getName()
, w przypadku braku informacji wrócą w czasie działania do domyślnego zachowania.
Podczas uwzględniania metadanych parametrów kompilatory muszą zawierać informacje o wygenerowanych klasach, takich jak wyliczenia, ponieważ metadane parametrów zawierają informacje o tym, czy parametr jest syntetyczny lub wymagany.
Adnotacja MethodParameters
opisuje tylko poszczególne parametry metody. Dlatego kompilatory mogą całkowicie pominąć adnotację w przypadku konstruktorów i metod, które nie mają parametrów, ze względu na rozmiar kodu i wydajność w czasie działania.
Tablice opisane poniżej muszą mieć taki sam rozmiar jak method_id_item
struktura dex powiązana z metodą. W przeciwnym razie w czasie działania programu zostanie zgłoszony wyjątek 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
.
Ponieważ MethodParameters
opisuje wszystkie parametry formalne metody, nawet te, które nie są jawnie ani niejawnie zadeklarowane w kodzie źródłowym, rozmiar tablic może się różnić od informacji o sygnaturze lub innych 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 odbiornika adnotacji typu, które nie występują w rzeczywistym podpisie metody.
Nazwa | Format | Opis |
---|---|---|
nazwy, | Ciąg znaków[] | Nazwy parametrów formalnych powiązanej metody. Tablica nie może mieć wartości null, ale musi być pusta, jeśli nie ma parametrów formalnych. Wartość w tablicy musi mieć wartość null, jeśli parametr formalny o tym indeksie nie ma nazwy. Jeśli ciągi nazw parametrów są puste lub zawierają znaki „.”, „;”, „[” lub „/”, w czasie działania programu zostanie zgłoszony błąd java.lang.reflect.MalformedParametersException .
|
accessFlags | int[] | Flagi dostępu parametrów formalnych powiązanej metody. Tablica nie może mieć wartości null, ale musi być pusta, jeśli nie ma parametrów formalnych. Wartość jest maską bitową o tych wartościach:
java.lang.reflect.MalformedParametersException .
|
dalvik.annotation.Signature
Wyświetla się w przypadku klas, pól i metod
Adnotacja Signature
jest dołączana do każdej klasy, pola lub metody, które są zdefiniowane za pomocą bardziej złożonego typu niż ten, który można przedstawić za pomocą type_id_item
. Format .dex
nie określa formatu podpisów. Ma on jedynie umożliwiać reprezentowanie podpisów wymaganych przez język źródłowy do prawidłowego wdrożenia semantyki tego języka. 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). Dlatego każde użycie podpisu powinno być zapisane w taki sposób, aby nie zakładać, że otrzymywane są tylko prawidłowe podpisy, i wyraźnie zabezpieczać się przed możliwością napotkania podpisu nieprawidłowego pod względem składni.
Ciągi sygnatur zwykle zawierają dużo powielonej treści, dlatego adnotacja Signature
jest definiowana jako tablica ciągów tekstowych, w której powielone elementy naturalnie odnoszą się do tych samych danych bazowych, a sygnatura jest traktowana jako połączenie wszystkich ciągów tekstowych w tablicy. Nie ma reguł dotyczących rozdzielania podpisu na osobne ciągi znaków. Zależy to całkowicie od narzędzi, które generują pliki .dex
.
Nazwa | Format | Opis |
---|---|---|
wartość | Ciąg znaków[] | sygnatura tej klasy lub tego elementu w postaci tablicy ciągów znaków, które należy połączyć ze sobą; |
dalvik.annotation.Throws
Pojawia się w metodach
Do każdej metody, która może zgłaszać co najmniej 1 typ wyjątku, jest dołączona adnotacja Throws
.
Nazwa | Format | Opis |
---|---|---|
wartość | Klasa[] | tablica zgłaszanych typów wyjątków, |