Dalvik 可執行格式

本文說明 .dex 檔案的版面配置和內容,這類檔案用於保存一組類別定義及其相關聯的附加資料。

類型指南

名稱 說明
byte 8 位元帶正負號整數
ubyte 8 位元不帶正負號的整數
short 16 位元帶正負號整數,小端序
ushort 16 位元不帶正負號的 int,小端序
int 32 位元帶正負號整數,小端序
uint 32 位元不帶正負號的 int,小端序
long 64 位元帶正負號整數,小端序
ulong 64 位元不帶正負號整數,小端序
sleb128 已簽署的 LEB128,長度可變 (請參閱下文)
uleb128 未簽署的 LEB128,長度可變 (請參閱下文)
uleb128p1 未簽署的 LEB128,外加 1,長度可變 (請見下文)

LEB128

LEB128 (「端序128」) 是任意有號或無號整數量的可變長度編碼。格式是從 DWARF3 規格借用而來。在 .dex 檔案中,LEB128 一律只用於編碼 32 位元數量。

每個 LEB128 編碼值都由一到五個位元組組成,共同代表單一 32 位元值。每個位元組都會設定最高有效位元,但序列中的最後一個位元組除外,該位元組會清除最高有效位元。每個位元組的其餘七個位元都是酬載,第一個位元組是數量的最低有效七個位元,第二個位元組是下一個七個位元,依此類推。如果是已簽署的 LEB128 (sleb128),序列中最後一個位元組的最高有效位元酬載會經過符號擴充,產生最終值。在未簽署的情況下 (uleb128),任何未明確表示的位元都會解讀為 0

雙位元組 LEB128 值的位元圖
第一個位元組 第二個位元組
1 位元6 bit5 bit4 bit3 位元2 bit1 bit0 0 bit13 bit12 bit11 位元10 bit9 bit8 bit7

變體 uleb128p1 用於表示已簽署的值,其中表示法為以 uleb128 編碼的「值加一」。這會將 -1 (也可以視為不帶正負號的值 0xffffffff) 編碼為單一位元組,但其他負數則不會,因此適用於代表的數字必須為非負數或 -1 (或 0xffffffff),且不允許其他負數值 (或不太可能需要大型不帶正負號的值) 的情況。

以下列舉幾個格式的範例:

編碼序列 sleb128 uleb128 uleb128p1
0000-1
01110
7f-1127126
80 7f-1281625616255

檔案版面配置

名稱 格式 說明
標頭 header_item 標題
string_ids string_id_item[] 字串 ID 清單。這些是這個檔案使用的所有字串的 ID,可用於內部命名 (例如型別描述元),或做為程式碼參照的常數物件。這份清單必須依字串內容排序,使用 UTF-16 碼位值 (而非依據語言代碼),且不得包含任何重複項目。
type_ids type_id_item[] 類型 ID 清單。這些是這個檔案參照的所有型別 (類別、陣列或原始型別) 的 ID,無論是否定義於檔案中。這份清單必須依 string_id 索引排序,且不得包含任何重複項目。
proto_ids proto_id_item[] 方法原型 ID 清單。這些是這個檔案參照的所有原型 ID。這份清單必須先依傳回型別 (依 type_id 索引) 排序,再依引數清單 (依字母順序排序,個別引數依 type_id 索引排序) 排序。清單不得包含任何重複項目。
field_ids field_id_item[] 欄位 ID 清單。這些是這個檔案參照的所有欄位 ID,無論是否定義於檔案中。這份清單必須經過排序,其中定義型別 (依 type_id 索引) 是主要順序,欄位名稱 (依 string_id 索引) 是中間順序,型別 (依 type_id 索引) 則是次要順序。清單不得包含重複項目。
method_ids method_id_item[] 方法 ID 清單。這些是這個檔案參照的所有方法 (無論是否在檔案中定義) 的 ID。這個清單必須經過排序,其中定義型別 (依 type_id 索引) 是主要順序,方法名稱 (依 string_id 索引) 是中間順序,方法原型 (依 proto_id 索引) 是次要順序。清單不得包含任何重複項目。
class_defs class_def_item[] 類別定義清單。類別的排序方式必須確保特定類別的超類別和實作介面,在清單中會出現在參照類別之前。此外,清單中不得出現同名類別的定義超過一次。
call_site_ids call_site_id_item[] 呼叫網站 ID 清單。這些是這個檔案參照的所有呼叫網站的 ID,無論是否定義於檔案中。這份清單必須依 call_site_off 遞增排序。
method_handles method_handle_item[] 方法會處理清單。這個檔案參照的所有方法控制代碼清單,無論是否定義於檔案中。這份清單未經過排序,且可能含有重複項目,這些項目在邏輯上會對應至不同的方法控制代碼例項。
資料 ubyte[] 資料區域,包含上述表格的所有支援資料。 不同項目有不同的對齊規定,且必要時會在每個項目之前插入填補位元組,以達到適當的對齊方式。
link_data ubyte[] 靜態連結檔案中使用的資料。本節中的資料格式未在本文件中指定。未連結的檔案中,這個部分是空白的,執行階段實作可視需要使用。

容器格式

第 41 版導入了 DEX 資料的新容器格式,目的是節省空間。這個容器格式可將多個邏輯 DEX 檔案合併為單一實體檔案。 新格式主要只是將舊格式的檔案天真地串連在一起,但仍有些差異:

  • file_size 是邏輯檔案的大小,而非實體檔案的大小。 可用於疊代容器中的所有邏輯檔案。
  • 邏輯 dex 檔案可以參照容器中的任何後續資料 (但不能參照先前的資料)。 這樣一來,DEX 檔案就能共用字串等資料。
  • 所有位移都是相對於實體檔案。沒有相對於標頭的位移。 這樣可確保具有位移的區段可在邏輯檔案之間共用。
  • 標頭新增了兩個欄位,用於描述容器的界線。 這項額外的檢查可確保一致性,並簡化程式碼移植至新格式的作業。
  • data_sizedata_off 現在已不再使用。 資料可以分散在多個邏輯檔案中,不一定要連續。

位元欄位、字串和常數定義

DEX_FILE_MAGIC

嵌入 header_item

常數陣列/字串 DEX_FILE_MAGIC 是位元組清單,必須出現在 .dex 檔案開頭,才能辨識為這類檔案。這個值刻意包含換行符 ("\n"0x0a) 和空值位元組 ("\0"0x00),有助於偵測特定形式的損毀。這個值也會將格式版本號碼編碼為三位數的十進位數字,隨著格式演進,這個數字預計會隨著時間單調遞增。

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

注意:Android 16 版新增支援格式的 041 版,支援容器格式

注意:Android 10.0 版新增支援 040 格式,並擴充 SimpleNames 中允許的字元集。

注意:Android 9.0 版本新增了對 039 格式的支援,並導入兩個新的位元碼:const-method-handleconst-method-type。(這些項目都會在「位元碼集摘要」表格中說明)。在 Android 10 中,版本 039 擴充了 DEX 檔案格式,納入僅適用於啟動類別路徑上 DEX 檔案的隱藏 API 資訊。

注意:Android 8.0 版本新增了對 038 格式版本的支援。版本 038 新增了位元組碼 (invoke-polymorphicinvoke-custom) 和方法控制代碼的資料。

注意:Android 7.0 版本新增了對 037 格式版本的支援。在 037 版之前,大多數 Android 版本都使用格式的 035 版。版本 035037 的唯一差異是新增了預設方法,並調整了 invoke

注意:至少有幾個較早版本的格式已用於廣泛發布的公開軟體。舉例來說,Android 平台 M3 版本 (2007 年 11 月至 12 月) 使用 009 版,Android 平台 M5 版本 (2008 年 2 月至 3 月) 則使用 013 版。在許多方面,這些舊版格式與本文所述版本有顯著差異。

ENDIAN_CONSTANT 和 REVERSE_ENDIAN_CONSTANT

嵌入 header_item

常數 ENDIAN_CONSTANT 用於指出檔案的位元組順序。雖然標準 .dex 格式為小端序,但實作時可選擇執行位元組交換。如果實作項目遇到 endian_tagREVERSE_ENDIAN_CONSTANT 而非 ENDIAN_CONSTANT 的標頭,就會知道檔案已從預期形式進行位元組交換。

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

NO_INDEX

嵌入 class_def_item 和 debug_info_item

常數 NO_INDEX 用於表示缺少索引值。

注意:這個值不會定義為 0,因為這通常是有效的索引。

NO_INDEX 的所選值可表示為 uleb128p1 編碼中的單一位元組。

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

存取旗標定義

嵌入 class_def_item、encoded_field、encoded_method 和 InnerClass

這些旗標的位元欄位用於指出類別和類別成員的存取權和整體屬性。

名稱 適用於類別 (和 InnerClass 註解) 適用於欄位 方法
ACC_PUBLIC 0x1 public:在任何地方都能看到 public:在任何地方都能看到 public:在任何地方都能看到
ACC_PRIVATE 0x2 * private:僅對定義類別可見 private:僅對定義類別可見 private:僅對定義類別可見
ACC_PROTECTED 0x4 * protected:套件和子類別可見 protected:套件和子類別可見 protected:套件和子類別可見
ACC_STATIC 0x8 * static:並非以外部 this參照建構 static:全域至定義類別 static:不接受 this 引數
ACC_FINAL 0x10 final:無法建立子類別 final:建構後即無法變更 final:無法覆寫
ACC_SYNCHRONIZED 0x20     synchronized:與這個方法呼叫相關聯的鎖定會自動取得。

注意:只有同時設定 ACC_NATIVE,這項設定才會生效。

ACC_VOLATILE 0x40   volatile:特殊存取規則,有助於確保討論串安全  
ACC_BRIDGE 0x40     橋接方法,由編譯器自動新增為型別安全橋接器
ACC_TRANSIENT 0x80   transient:預設序列化不會儲存  
ACC_VARARGS 0x80     編譯器應將最後一個引數視為「餘數」引數
ACC_NATIVE 0x100     native:以原生程式碼實作
ACC_INTERFACE 0x200 interface:可多次實作的抽象類別    
ACC_ABSTRACT 0x400 abstract:無法直接例項化   abstract:這個類別未實作
ACC_STRICT 0x800     strictfp:浮點運算的嚴格規則
ACC_SYNTHETIC 0x1000 並非直接在原始碼中定義 並非直接在原始碼中定義 並非直接在原始碼中定義
ACC_ANNOTATION 0x2000 宣告為註解類別    
ACC_ENUM 0x4000 宣告為列舉型別 宣告為列舉值  
(未使用) 0x8000      
ACC_CONSTRUCTOR 0x10000     建構函式方法 (類別或例項初始設定式)
ACC_DECLARED_
SYNCHRONIZED
0x20000     宣告的元素數量為 synchronized 個。

注意:這不會影響執行作業 (除了反映這個旗標本身之外)。

* 僅允許在 InnerClass 註解中使用,且不得在 class_def_item 中使用。

修正後的 UTF-8 編碼

為方便支援舊版,.dex 格式會以事實上的標準修改 UTF-8 形式編碼字串資料,以下稱為 MUTF-8。這個表單與標準 UTF-8 相同,但有以下例外狀況:

  • 僅使用一、二和三位元組編碼。
  • 範圍 U+10000U+10ffff 中的碼點會編碼為代理配對,每個碼點都以三位元組編碼值表示。
  • 程式碼點 U+0000 會以雙位元組形式編碼。
  • 如為標準 C 語言解讀,一般空值位元組 (值 0) 表示字串結尾。

上述前兩項可歸納為:MUTF-8 是 UTF-16 的編碼格式,而非 Unicode 字元的直接編碼格式。

上述最後兩項功能可同時在字串 中加入程式碼點 U+0000,並以 C 樣式的空值終止字串操控該字串。

不過,由於 U+0000 的特殊編碼方式,與一般 UTF-8 不同,因此在 MUTF-8 字串配對上呼叫標準 C 函式 strcmp() 時,結果不一定會指出不相等字串的正確簽署比較結果。如果需要排序 (而不只是比較是否相等),最直接的比較 MUTF-8 字串方式是逐一解碼字元,然後比較解碼值。(不過,您也可以採用更聰明的做法)。

如要進一步瞭解字元編碼,請參閱 Unicode 標準。事實上,MUTF-8 比較接近 (相對較不為人知的) 編碼 CESU-8,而非 UTF-8 本身。

encoded_value 編碼

嵌入 annotation_element 和 encoded_array_item

encoded_value 是經過編碼的 (近乎) 任意階層式結構化資料。編碼的目的是要簡潔,且易於剖析。

名稱 格式 說明
(value_arg << 5) | value_type ubyte 位元組,指出緊接在後續 value 的類型,以及高階三個位元中的選用說明引數。請參閱下方的各種value定義。 在大多數情況下,value_arg 會以位元組為單位,編碼緊接在後的 value 長度,如 (size - 1),例如 0 表示值需要一個位元組,7 則表示需要八個位元組;不過,如下所述,也有例外情形。
ubyte[] 代表值的位元組,長度可變,且對於不同的 value_type 位元組,解讀方式也不同,但一律為小端序。詳情請參閱下方的各種值定義。

值格式

類型名稱 value_type value_arg 格式 value 格式 說明
VALUE_BYTE 0x00 (無;必須為 0) ubyte[1] 帶正負號的單一位元組整數值
VALUE_SHORT 0x02 大小 - 1 (0…1) ubyte[size] 帶正負號的雙位元組整數值,經過正負號擴充
VALUE_CHAR 0x03 大小 - 1 (0…1) ubyte[size] 不帶正負號的雙位元組整數值,以零擴充
VALUE_INT 0x04 大小 - 1 (0…3) ubyte[size] 帶正負號的四位元組整數值,經過正負號擴充
VALUE_LONG 0x06 大小 - 1 (0…7) ubyte[size] 帶正負號的八位元組整數值,經過正負號擴充
VALUE_FLOAT 0x10 大小 - 1 (0…3) ubyte[size] 四位元組位元模式,向右以零擴充,並解讀為 IEEE754 32 位元浮點值
VALUE_DOUBLE 0x11 大小 - 1 (0…7) ubyte[size] 八位元組位元模式,向右以零擴充,並解讀為 IEEE754 64 位元浮點值
VALUE_METHOD_TYPE 0x15 大小 - 1 (0…3) ubyte[size] 未簽署 (以零擴充) 的四位元組整數值,解讀為 proto_ids 區段的索引,代表方法型別值
VALUE_METHOD_HANDLE 0x16 大小 - 1 (0…3) ubyte[size] 未簽署 (以零擴充) 的四位元組整數值,解讀為 method_handles 區段的索引,代表方法控制代碼值
VALUE_STRING 0x17 大小 - 1 (0…3) ubyte[size] 未簽署 (以零擴充) 的四位元組整數值,解讀為 string_ids 區段的索引,代表字串值
VALUE_TYPE 0x18 大小 - 1 (0…3) ubyte[size] 未簽署 (以零擴充) 四位元組整數值,解讀為 type_ids 區段的索引,代表反射型別/類別值
VALUE_FIELD 0x19 大小 - 1 (0…3) ubyte[size] 未簽署 (以零擴充) 四位元組整數值,解讀為 field_ids 區段的索引,代表反射欄位值
VALUE_METHOD 0x1a 大小 - 1 (0…3) ubyte[size] 未簽署 (以零擴充) 的四位元組整數值,解讀為 method_ids 區段的索引,代表反射方法值
VALUE_ENUM 0x1b 大小 - 1 (0…3) ubyte[size] 無正負號 (以零擴充) 四位元組整數值,解讀為 field_ids 區段的索引,代表列舉型別常數的值
VALUE_ARRAY 0x1c (無;必須為 0) encoded_array 值陣列,格式如下方「encoded_array 格式」所述。value 的大小隱含於編碼中。
VALUE_ANNOTATION 0x1d (無;必須為 0) encoded_annotation 子註解,格式如下方「encoded_annotation 格式」所述。value 的大小隱含於編碼中。
VALUE_NULL 0x1e (無;必須為 0) (無) null 參考值
VALUE_BOOLEAN 0x1f 布林值 (0…1) (無) 一位元值;0 代表 false1 代表 true。位元以 value_arg 表示。

encoded_array 格式

名稱 格式 說明
size uleb128 陣列中的元素數量
encoded_value[size] 一系列 size encoded_value 位元組序列,格式如本節所述,並依序串連。

encoded_annotation 格式

名稱 格式 說明
type_idx uleb128 註解類型。這必須是類別 (而非陣列或原始) 型別。
size uleb128 這個註解中的名稱/值對應數量
元素 annotation_element[size] 註解元素,直接以行內形式表示 (而非以位移表示)。元素必須依遞增順序按 string_id 索引排序。

註解元素格式

名稱 格式 說明
name_idx uleb128 元素名稱,以 string_ids 區段的索引表示。這個字串必須符合上述定義的 MemberName 語法。
encoded_value 元素值

字串語法

.dex 檔案中的項目種類繁多,但最終都會參照字串。下列 BNF 樣式的定義指出這些字串可接受的語法。

SimpleName

SimpleName 是其他項目名稱語法的基礎。.dex 格式在此處允許相當大的自由度 (遠超過大多數常見來源語言)。簡單來說,簡單名稱包含任何低 ASCII 字母或數字、幾個特定的低 ASCII 符號,以及大多數非 ASCII 程式碼點 (不屬於控制、空格或特殊字元)。從 040 版開始,格式也允許使用空格字元 (Unicode Zs 類別)。請注意,替代碼點 (範圍為 U+d800U+dfff) 本身並非有效名稱字元,但 Unicode 補充字元有效字元 (以 SimpleNameChar 規則的最終替代項目表示),且應以 MUTF-8 編碼的替代碼點配對形式表示在檔案中。

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

MemberName

由 field_id_item 和 method_id_item 使用

MemberName 是類別成員的名稱,成員包括欄位、方法和內部類別。

MemberName
SimpleName
| '<' SimpleName '>'

FullClassName

FullClassName 是完整類別名稱,包括選用的套件指定符,後面接著必要名稱。

FullClassName
OptionalPackagePrefix SimpleName
OptionalPackagePrefix
(SimpleName '/')*

TypeDescriptor

由 type_id_item 使用

TypeDescriptor 是任何型別的表示法,包括基本型別、類別、陣列和 void。請參閱下文,瞭解各個版本的意義。

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

ShortyDescriptor

proto_id_item 使用

ShortyDescriptor 是方法原型的簡短形式表示法,包括傳回和參數型別,但各種參照 (類別或陣列) 型別之間沒有區別。而是以單一 'L' 字元表示所有參照型別。

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

TypeDescriptor 語意

這是 TypeDescriptor 各個變體的意義。

語法 意義
V void;僅適用於退貨類型
Z boolean
B byte
short
C char
I int
J long
F float
D double
Lfully/qualified/Name; 類別 fully.qualified.Name
[descriptor descriptor 陣列,可遞迴用於陣列的陣列,但維度不得超過 255 個。

項目和相關結構

本節包含 .dex 檔案中可能出現的各個頂層項目定義。

header_item

顯示在頁首區段

對齊:4 個位元組

名稱 格式 說明
魔法 ubyte[8] = DEX_FILE_MAGIC 魔法值。詳情請參閱上文「DEX_FILE_MAGIC」一節的討論內容。
檢查碼 uint 檔案其餘部分的 adler32 檢查碼 (除了 magic 和這個欄位以外的所有內容);用於偵測檔案損毀情形
簽名 ubyte[20] 檔案其餘部分的 SHA-1 簽章 (雜湊) (magicchecksum 和這個欄位以外的所有內容);用於唯一識別檔案
file_size uint

整個檔案 (包括標頭) 的大小,以位元組為單位 (v40 或更早版本)

從這個標頭的開頭到下一個標頭或整個檔案 (容器) 結尾的距離 (以位元組為單位)。(v41 以上版本)

header_size uint

標頭大小 (整個部分),以位元組為單位。這樣一來,至少能確保有限的回溯/前向相容性,且不會使格式失效。

必須為 0x70 (112) 個位元組 (v40 或更早版本)

必須為 0x78 (120) 個位元組 (v41 以上版本)

endian_tag uint = ENDIAN_CONSTANT endianness 標記。詳情請參閱上文「ENDIAN_CONSTANTREVERSE_ENDIAN_CONSTANT」的討論內容。
link_size uint 連結區段的大小,或 0 (如果這個檔案未靜態連結)
link_off uint 從檔案開頭到連結部分的位移,或 0 (如果 link_size == 0)。如果偏移量不是零,則應為 link_data 區段的偏移量。這份文件未指定所指資料的格式;這個標頭欄位 (和前一個欄位) 會保留為供執行階段實作使用的掛鉤。
map_off uint 從檔案開頭到對應地圖項目的偏移量。位移必須為非零值,應是 data 區段的位移,且資料應採用下方「map_list」指定的格式。
string_ids_size uint 字串 ID 清單中的字串數量
string_ids_off uint 從檔案開頭到字串 ID 清單的位移,或 0 (誠然是奇怪的極端情況)。string_ids_size == 0如果偏移量不為零,則應為 string_ids 區段的開頭。
type_ids_size uint 型別 ID 清單中的元素數量,最多 65535 個
type_ids_off uint 從檔案開頭到型別 ID 清單的偏移量,或 0 (確實是奇怪的極端情況)。type_ids_size == 0如果偏移量不為零,則應為 type_ids 區段的開頭。
proto_ids_size uint 原型 ID 清單中的元素數量,最多 65535 個
proto_ids_off uint 從檔案開頭到原型 ID 清單的偏移量,或 0 (誠實地說,這是奇怪的極端情況)。proto_ids_size == 0如果偏移量不為零,則應為 proto_ids 區段的開頭。
field_ids_size uint 欄位 ID 清單中的元素數量
field_ids_off uint 從檔案開頭到欄位 ID 清單的位移,或 0 (如果 field_ids_size == 0)。如果偏移量不為零,則應指向 field_ids 區段的開頭。
method_ids_size uint 方法 ID 清單中的元素數量
method_ids_off uint 從檔案開頭到方法 ID 清單的位移,或 0 (如果 method_ids_size == 0)。如果偏移量不為零,則應指向 method_ids 區段的開頭。
class_defs_size uint 類別定義清單中的元素數量
class_defs_off uint 從檔案開頭到類別定義清單的位移,或 0 (確實是奇怪的極端情況)。class_defs_size == 0如果偏移量不為零,則應為 class_defs 區段的開頭。
data_size uint

data 區段的大小 (以位元組為單位)。必須是 sizeof(uint) 的偶數倍數。 (v40 或更早版本)

未使用 (v41 以上版本)

data_off uint

從檔案開頭到 data 區段開頭的位移 (v40 或更早版本)

未使用 (v41 以上版本)

container_size uint

這個欄位不存在。可假設等於 file_size(v40 或更早版本)

整個檔案的大小 (包括其他 DEX 標頭及其資料)。 (v41 以上版本)

header_offset uint

這個欄位不存在。可假設等於 0(v40 或更早版本)

從檔案開頭到這個標頭開頭的偏移量。 (v41 以上版本)

map_list

顯示在「資料」部分

從 header_item 參照

對齊:4 個位元組

這份清單會依序顯示檔案的完整內容。相較於 header_item,這個函式包含一些多餘的內容,但目的是要提供簡單易用的表單,以便對整個檔案進行疊代。地圖中每個類型最多只能出現一次,但類型出現的順序沒有限制,格式其餘部分所隱含的限制除外 (例如,header 區段必須先出現,接著是 string_ids 區段等)。此外,地圖項目必須依初始偏移量排序,且不得重疊。

名稱 格式 說明
size uint 清單大小 (以項目為單位)
清單 map_item[size] 清單中的元素

map_item 格式

名稱 格式 說明
類型 ushort 項目類型 (請參閱下表)
unused ushort (未使用)
size uint 在指定偏移量找到的項目數量
碳補償 uint 從檔案開頭到有問題項目的偏移量

輸入驗證碼

項目類型 常數 項目大小 (以位元組為單位)
header_item TYPE_HEADER_ITEM 0x0000 0x70
string_id_item TYPE_STRING_ID_ITEM 0x0001 0x04
type_id_item TYPE_TYPE_ID_ITEM 0x0002 0x04
proto_id_item TYPE_PROTO_ID_ITEM 0x0003 0x0c
field_id_item TYPE_FIELD_ID_ITEM 0x0004 0x08
method_id_item TYPE_METHOD_ID_ITEM 0x0005 0x08
class_def_item TYPE_CLASS_DEF_ITEM 0x0006 0x20
call_site_id_item TYPE_CALL_SITE_ID_ITEM 0x0007 0x04
method_handle_item TYPE_METHOD_HANDLE_ITEM 0x0008 0x08
map_list TYPE_MAP_LIST 0x1000 4 + (item.size * 12)
type_list TYPE_TYPE_LIST 0x1001 4 + (item.size * 2)
annotation_set_ref_list TYPE_ANNOTATION_SET_REF_LIST 0x1002 4 + (item.size * 4)
annotation_set_item TYPE_ANNOTATION_SET_ITEM 0x1003 4 + (item.size * 4)
class_data_item TYPE_CLASS_DATA_ITEM 0x2000 隱含;必須剖析
code_item TYPE_CODE_ITEM 0x2001 隱含;必須剖析
string_data_item TYPE_STRING_DATA_ITEM 0x2002 隱含;必須剖析
debug_info_item TYPE_DEBUG_INFO_ITEM 0x2003 隱含;必須剖析
annotation_item TYPE_ANNOTATION_ITEM 0x2004 隱含;必須剖析
encoded_array_item TYPE_ENCODED_ARRAY_ITEM 0x2005 隱含;必須剖析
annotations_directory_item TYPE_ANNOTATIONS_DIRECTORY_ITEM 0x2006 隱含;必須剖析
hiddenapi_class_data_item TYPE_HIDDENAPI_CLASS_DATA_ITEM 0xF000 隱含;必須剖析

string_id_item

顯示在 string_ids 區段中

對齊:4 個位元組

名稱 格式 說明
string_data_off uint 從檔案開頭到這個項目的字串資料的位移。位移應指向 data 區段中的位置,且資料應採用下方「string_data_item」指定的格式。位移量沒有對齊規定。

string_data_item

顯示在「資料」部分

對齊方式:無 (位元組對齊)

名稱 格式 說明
utf16_size uleb128 這個字串的大小,以 UTF-16 程式碼單元為單位 (在許多系統中,這是「字串長度」)。也就是字串的解碼長度。(編碼長度是由 0 位元組的位置所隱含)。
資料 ubyte[] 一系列 MUTF-8 程式碼單元 (又稱八位元組或位元組),後接值為 0 的位元組。如需資料格式的詳細資料和討論內容,請參閱上方的「MUTF-8 (改良式 UTF-8) 編碼」。

注意:字串可包含 (編碼形式的) UTF-16 替代碼單元 (即 U+d800U+dfff),無論是單獨存在,還是相對於 Unicode 編碼為 UTF-16 的順序而言是無效的,都沒問題。如果適當,字串的較高層級用途可拒絕這類無效編碼。

type_id_item

顯示在 type_ids 區段中

對齊:4 個位元組

名稱 格式 說明
descriptor_idx uint 索引到此型別的描述元字串清單中。string_ids字串必須符合上述定義的 TypeDescriptor 語法。

proto_id_item

顯示在 proto_ids 區段中

對齊:4 個位元組

名稱 格式 說明
shorty_idx uint 這個原型的簡短形式描述元字串在 string_ids 清單中的索引。字串必須符合上述定義的 ShortyDescriptor 語法,且必須對應這個項目的傳回型別和參數。
return_type_idx uint index into the type_ids list for the return type of this prototype
parameters_off uint 從檔案開頭到這個原型參數類型清單的位移,如果這個原型沒有參數,則為 0。如果這個位移量不為零,則應位於 data 區段中,且該處的資料應採用下方 "type_list" 指定的格式。此外,清單中不應參照 void 型別。

field_id_item

顯示在 field_ids 區段中

對齊:4 個位元組

名稱 格式 說明
class_idx ushort 這個欄位定義者的 type_ids 清單索引。這必須是類別型別,而非陣列或原始型別。
type_idx ushort 這個欄位類型的 type_ids 清單索引
name_idx uint index into the string_ids list for the name of this field. 這個字串必須符合上述定義的 MemberName 語法。

method_id_item

顯示在 method_ids 區段中

對齊:4 個位元組

名稱 格式 說明
class_idx ushort 這個方法的定義者在 type_ids 清單中的索引。這必須是類別或陣列型別,而非原始型別。
proto_idx ushort 這個方法的原型索引到 proto_ids 清單中
name_idx uint 索引至這個方法的名稱的 string_ids 清單。這個字串必須符合上述定義的 MemberName 語法。

class_def_item

顯示在 class_defs 區段中

對齊:4 個位元組

名稱 格式 說明
class_idx uint 這個類別的 type_ids 清單索引。 這必須是類別型別,而非陣列或原始型別。
access_flags uint 類別的存取權標記 (publicfinal 等)。詳情請參閱「access_flags定義」。
superclass_idx uint 父類別的 type_ids 清單索引,或如果這個類別沒有父類別 (即根類別,例如 Object),則為常數值 NO_INDEX。如果存在,這必須是類別型別,而非陣列或原始型別。
interfaces_off uint 從檔案開頭到介面清單的位移,或0 (如果沒有)。這個位移應位於 data 區段中,且該處的資料應採用下方「type_list」指定的格式。清單中的每個元素都必須是類別型別 (而非陣列或原始型別),且不得有重複項目。
source_file_idx uint 索引到 string_ids 清單,取得包含這個類別 (至少是大部分) 原始來源的檔案名稱,或是代表缺少這項資訊的特殊值 NO_INDEX。任何指定方法的 debug_info_item 都可能覆寫這個來源檔案,但預期大多數類別只會來自一個來源檔案。
annotations_off uint 從檔案開頭到這個類別的註解結構體的偏移量,如果這個類別沒有註解,則為 0。如果這個位移不是零,則應位於 data 區段,且該處的資料應採用下方「annotations_directory_item」指定的格式,所有項目都應將這個類別視為定義者。
class_data_off uint 從檔案開頭到這個項目的相關聯類別資料的位移,如果這個類別沒有類別資料,則為 0。(舉例來說,如果這個類別是標記介面,就可能發生這種情況)。如果位移不是零,則應位於 data 區段,且該處的資料應採用下方「class_data_item」指定的格式,所有項目都應將這個類別視為定義者。
static_values_off uint 從檔案開頭到 static 欄位初始值清單的偏移量,如果沒有任何初始值 (且所有 static 欄位都要以 0null 初始化),則為 0。這個偏移量應位於 data 區段,且該處的資料應採用下方「encoded_array_item」指定的格式。陣列大小不得超過這個類別宣告的 static 欄位數量,且元素對應的 static 欄位順序必須與相應 field_list 中宣告的順序相同。每個陣列元素類型都必須與對應欄位的宣告類型相符。如果陣列中的元素數量少於 static 欄位,則剩餘欄位會以適當型別的 0null 初始化。

call_site_id_item

顯示在 call_site_ids 區段中

對齊:4 個位元組

名稱 格式 說明
call_site_off uint 從檔案開頭到呼叫網站定義的位移。位移應位於資料部分,且資料格式應符合下方「call_site_item」指定的格式。

call_site_item

顯示在「資料」部分

對齊方式:無 (位元組對齊)

call_site_item 是 encoded_array_item,其元素對應於提供給啟動程序連結器方法的引數。前三個引數如下:

  1. 代表啟動載入程式連結器方法的方法控制代碼 (VALUE_METHOD_HANDLE)。
  2. 啟動程序連結器應解析的方法名稱 (VALUE_STRING)。
  3. 與要解析的方法名稱類型 (VALUE_METHOD_TYPE) 對應的方法類型。

任何其他引數都是傳遞至啟動連結器方法的常數值。這些引數會依序傳遞,且不會進行任何類型轉換。

代表啟動載入連結器方法的處理常式方法必須具有 java.lang.invoke.CallSite 傳回型別。前三種參數類型如下:

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

任何其他引數的參數類型,都是根據常數值判斷。

method_handle_item

顯示在 method_handles 區段中

對齊:4 個位元組

名稱 格式 說明
method_handle_type ushort 方法控制代碼的類型;請參閱下表
unused ushort (未使用)
field_or_method_id ushort 欄位或方法 ID,取決於方法控制代碼類型是存取子還是方法呼叫器
unused ushort (未使用)

方法控制代碼類型代碼

常數 說明
METHOD_HANDLE_TYPE_STATIC_PUT 0x00 方法控制代碼是靜態欄位設定器 (存取子)
METHOD_HANDLE_TYPE_STATIC_GET 0x01 方法控制代碼是靜態欄位 Getter (存取子)
METHOD_HANDLE_TYPE_INSTANCE_PUT 0x02 方法控制代碼是執行個體欄位設定器 (存取子)
METHOD_HANDLE_TYPE_INSTANCE_GET 0x03 方法控制代碼是執行個體欄位擷取器 (存取子)
METHOD_HANDLE_TYPE_INVOKE_STATIC 0x04 方法控制代碼是靜態方法呼叫器
METHOD_HANDLE_TYPE_INVOKE_INSTANCE 0x05 方法控制代碼是執行個體方法呼叫器
METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR 0x06 方法控制代碼是建構函式方法呼叫器
METHOD_HANDLE_TYPE_INVOKE_DIRECT 0x07 方法控制代碼是直接方法呼叫器
METHOD_HANDLE_TYPE_INVOKE_INTERFACE 0x08 方法控制代碼是介面方法叫用程式

class_data_item

參照自 class_def_item

顯示在「資料」部分

對齊方式:無 (位元組對齊)

名稱 格式 說明
static_fields_size uleb128 這個項目中定義的靜態欄位數量
instance_fields_size uleb128 這個項目中定義的執行個體欄位數量
direct_methods_size uleb128 這個項目中定義的直接方法數量
virtual_methods_size uleb128 這個項目中定義的虛擬方法數量
static_fields encoded_field[static_fields_size] 定義的靜態欄位,以編碼元素序列表示。欄位必須依遞增順序以 field_idx 排序。
instance_fields encoded_field[instance_fields_size] 定義的執行個體欄位,以編碼元素序列表示。欄位必須依遞增順序以 field_idx 排序。
direct_methods encoded_method[direct_methods_size] 定義的直接 (任何 staticprivate 或建構函式) 方法,以編碼元素序列表示。方法必須依遞增順序排序。 method_idx
virtual_methods encoded_method[virtual_methods_size] 定義的虛擬 (非 staticprivate 或建構函式) 方法,以編碼元素序列表示。除非這個項目代表的類別覆寫了方法,否則這份清單不應包含繼承的方法。方法必須依 method_idx 遞增排序。虛擬方法的 method_idx 不得與任何直接方法相同。

注意:所有元素的 field_idmethod_id 執行個體都必須參照相同的定義類別。

encoded_field 格式

名稱 格式 說明
field_idx_diff uleb128 索引到這個欄位的身分識別 (包括名稱和描述元) 的 field_ids 清單中,以與清單中前一個元素的索引差異表示。清單中第一個元素的索引會直接表示。
access_flags uleb128 欄位的存取權標記 (publicfinal 等)。詳情請參閱「access_flags定義」。

encoded_method 格式

名稱 格式 說明
method_idx_diff uleb128 索引到這個方法的 ID 的 method_ids 清單中 (包括名稱和描述元),以清單中前一個元素的索引差異表示。清單中第一個元素的索引會直接表示。
access_flags uleb128 方法的存取權標記 (publicfinal 等)。詳情請參閱「access_flags定義」。
code_off uleb128 從檔案開頭到這個方法的程式碼結構的位移,或 0 (如果這個方法是 abstractnative)。偏移量應指向 data 部分中的位置。資料格式由「code_item」指定,如下所示: "code_item"。

type_list

從 class_def_item 和 proto_id_item 參照

顯示在「資料」部分

對齊:4 個位元組

名稱 格式 說明
size uint 清單大小 (以項目為單位)
清單 type_item[size] 清單中的元素

type_item 格式

名稱 格式 說明
type_idx ushort type_ids 清單的索引

code_item

參照自 encoded_method

顯示在「資料」部分

對齊:4 個位元組

名稱 格式 說明
registers_size ushort 這段程式碼使用的暫存器數量
ins_size ushort 這個程式碼所屬方法傳入引數的字數
outs_size ushort 這個程式碼的方法調用所需的傳出引數空間字數
tries_size ushort 此執行個體的 try_item 數量。如果不是零,這些值會顯示為這個例項中 insns 後方的 tries 陣列。
debug_info_off uint 從檔案開頭到這個程式碼的偵錯資訊 (行號 + 本機變數資訊) 序列的偏移,或 0 (如果沒有任何資訊)。如果偏移量不是零,則應指向 data 區段中的位置。資料格式由下方的「debug_info_item」指定。
insns_size uint 指令清單的大小 (以 16 位元程式碼單元為單位)
insns ushort[insns_size] 實際位元碼陣列。insns 陣列中的程式碼格式由隨附文件「Dalvik 位元碼」指定。請注意,雖然這是定義為 ushort 的陣列,但有些內部結構偏好四位元組對齊。此外,如果這是位元組順序互換的檔案,則會對個別 ushort 例項執行互換,不會對較大的內部結構執行互換。
padding ushort (optional) = 0 兩個位元組的邊框間距,使 tries 對齊四個位元組。 只有在 tries_size 不是零且 insns_size 為奇數時,才會顯示這個元素。
tries try_item[tries_size] (選用) 陣列,指出程式碼中例外狀況的擷取位置,以及如何處理這些例外狀況。陣列元素不得重疊,且必須依位址由低到高排序。只有在 tries_size 不是零時,才會出現這個元素。
處理常式 encoded_catch_handler_list (選用) 代表一連串擷取類型和相關聯處理常式位址的位元組。每個 try_item 都有這個結構的位元組偏移。只有在 tries_size 不是零時,才會出現這個元素。

try_item 格式

名稱 格式 說明
start_addr uint 這個項目涵蓋的程式碼區塊起始位址。這個位址是第一個涵蓋指令開頭的 16 位元程式碼單元計數。
insn_count ushort 這個項目涵蓋的 16 位元代碼單元數量。最後涵蓋的程式碼單元 (含) 為 start_addr + insn_count - 1
handler_off ushort 這個項目的相關 encoded_catch_hander_list 的開始位置到 encoded_catch_handler 的位元組偏移量。這必須是 encoded_catch_handler 開始的偏移量。

encoded_catch_handler_list 格式

名稱 格式 說明
size uleb128 這個清單的大小 (以項目為單位)
清單 encoded_catch_handler[handlers_size] 處理常式清單的實際清單,直接表示 (而非以偏移量表示),並依序串連

encoded_catch_handler 格式

名稱 格式 說明
size sleb128 這份清單中的捕捉類型數量。如果為非正數,則這是擷取型別數量的負數,且擷取作業後會接續執行擷取所有項目的處理常式。舉例來說,size0 表示有 catch-all,但沒有明確型別的 catches。size2 表示有兩個明確型別的 catch,但沒有 catch-all。而 size-1 表示有一個已輸入的擷取內容和一個擷取所有內容。
處理常式 encoded_type_addr_pair[abs(size)] abs(size) 編碼項目的串流,每個擷取的型別各有一個項目,順序應與型別的測試順序相同。
catch_all_addr uleb128 (選用) 全部接收處理常式的位元組碼位址。只有在 size 為非正數時,才會出現這個元素。

encoded_type_addr_pair 格式

名稱 格式 說明
type_idx uleb128 index into the type_ids list for the type of the exception to catch
addr uleb128 相關聯例外狀況處理常式的位元碼位址

debug_info_item

參照自 code_item

顯示在「資料」部分

對齊方式:無 (位元組對齊)

每個 debug_info_item 都會定義 DWARF3 啟發的位元組編碼狀態機器,解譯時會發出位置資料表和 (可能) code_item 的本機變數資訊。序列開頭為長度可變的標頭 (長度取決於方法參數數量),後面接著狀態機位元組碼,結尾為 DBG_END_SEQUENCE 位元組。

狀態機器包含五個暫存器。address 暫存器代表相關聯 insns_item 中的指令偏移,以 16 位元程式碼單元表示。address 暫存器會在每個debug_info序列的開頭從 0 開始,且只能單調遞增。line 暫存器代表應與狀態機器發出的下一個位置資料表項目相關聯的來源行號。此值會在序列標頭中初始化,且可能會朝正向或負向變更,但絕不能小於 1source_file 暫存器代表行號項目參照的來源檔案。系統會將其初始化為 class_def_item 中的 source_file_idx 值。另外兩個變數 prologue_endepilogue_begin 是布林值標記 (初始化為 false),指出下一個發出的位置是否應視為方法序言或結尾。狀態機器也必須追蹤每個暫存器中最後一個本機變數的名稱和型別,以供 DBG_RESTART_LOCAL 程式碼使用。

標頭如下:

名稱 格式 說明
line_start uleb128 狀態機 line 暫存器的初始值。 不代表實際職位項目。
parameters_size uleb128 編碼的參數名稱數量。每個方法參數應各有一個,但例項方法的 this 除外 (如有)。
parameter_names uleb128p1[parameters_size] 方法參數名稱的字串索引。NO_INDEX 的編碼值表示相關聯的參數沒有名稱。型別描述元和簽章是從方法描述元和簽章推斷而來。

位元組碼值如下:

名稱 格式 引數 說明
DBG_END_SEQUENCE 0x00 (無) 終止 code_item 的偵錯資訊序列
DBG_ADVANCE_PC 0x01 uleb128 addr_diff addr_diff:要加到位址暫存器的金額 推進位址暫存器,但不發出位置項目
DBG_ADVANCE_LINE 0x02 sleb128 line_diff line_diff:要變更的收銀機金額 推進行號暫存器,但不發出位置項目
DBG_START_LOCAL 0x03 uleb128 register_num
uleb128p1 name_idx
uleb128p1 type_idx
register_num:包含本機的暫存器
name_idx:名稱的字串索引
type_idx:類型的類型索引
在目前地址導入區域變數。name_idxtype_idx 可以是 NO_INDEX,表示該值不明。
DBG_START_LOCAL_EXTENDED 0x04 uleb128 register_num
uleb128p1 name_idx
uleb128p1 type_idx
uleb128p1 sig_idx
register_num:包含本機的暫存器
name_idx:名稱的字串索引
type_idx:類型的類型索引
sig_idx:類型簽章的字串索引
在目前位址導入具有型別簽章的區域。 name_idxtype_idxsig_idx 都可以是 NO_INDEX,表示該值不明。(不過,如果 sig_idx-1,則可使用運算碼 DBG_START_LOCAL 更有效率地表示相同資料)。

注意:請參閱下方「dalvik.annotation.Signature」一節的討論內容,瞭解處理簽章的注意事項。

DBG_END_LOCAL 0x05 uleb128 register_num register_num:包含本機的登錄 在目前的位址將目前有效的本機變數標示為超出範圍
DBG_RESTART_LOCAL 0x06 uleb128 register_num register_num:註冊以重新啟動 在目前位址重新導入區域變數。名稱和型別與指定暫存器中最後一個即時的本機相同。
DBG_SET_PROLOGUE_END 0x07 (無) 設定 prologue_end 狀態機暫存器,指出新增的下一個位置項目應視為方法序言的結尾 (方法中斷點的適當位置)。任何特殊 (>= 0x0a) 不透明指令碼都會清除 prologue_end 暫存器。
DBG_SET_EPILOGUE_BEGIN 0x08 (無) 會設定 epilogue_begin 狀態機暫存器,指出新增的下一個位置項目應視為方法結尾的開頭 (適合在方法結束前暫停執行的位置)。任何特殊 (>= 0x0a) 不正確的運算碼都會清除 epilogue_begin 暫存器。
DBG_SET_FILE 0x09 uleb128p1 name_idx name_idx:來源檔案名稱的字串索引;如果不明,則為 NO_INDEX 表示後續所有行號項目都會參照這個來源檔案名稱,而非 code_item 中指定的預設名稱。
特殊運算碼 0x0a…0xff (無) 推進 lineaddress 暫存器、發出位置項目,並清除 prologue_endepilogue_begin。說明如下。

特殊運算碼

值介於 0x0a0xff (含) 之間的運算碼會將 lineaddress 暫存器移動少量,然後發出新的位置表項目。增量的公式如下:

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

adjusted_opcode = opcode - DBG_FIRST_SPECIAL

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

annotations_directory_item

參照自 class_def_item

顯示在「資料」部分

對齊:4 個位元組

名稱 格式 說明
class_annotations_off uint 從檔案開頭到直接在類別上建立的註解之間的位移,或 0 (如果類別沒有直接註解)。如果偏移量不是零,則應指向 data 區段中的位置。資料格式由下方的「annotation_set_item」指定。
fields_size uint 這個項目註解的欄位數
annotated_methods_size uint 這個項目註解的方法數量
annotated_parameters_size uint 這個項目註解的方法參數清單數量
field_annotations field_annotation[fields_size] (選用) 相關聯的欄位註解清單。清單中的元素必須依 field_idx 遞增排序。
method_annotations method_annotation[methods_size] (選用) 相關方法註解清單。清單中的元素必須依 method_idx 遞增排序。
parameter_annotations parameter_annotation[parameters_size] (選用) 相關方法參數註解的清單。清單中的元素必須依 method_idx 遞增排序。

注意:所有元素的 field_idmethod_id 執行個體都必須參照相同的定義類別。

field_annotation 格式

名稱 格式 說明
field_idx uint 要註解的欄位身分識別的 field_ids 清單索引
annotations_off uint 從檔案開頭到欄位註解清單的偏移量。偏移量應指向 data 區段中的位置。資料格式由「annotation_set_item」指定,如下所示: "annotation_set_item"。

method_annotation 格式

名稱 格式 說明
method_idx uint 方法註解的 ID method_ids 清單索引
annotations_off uint 從檔案開頭到方法註解清單的位移。偏移量應指向 data 部分中的位置。資料格式由「annotation_set_item」指定,如下所示: "annotation_set_item"。

parameter_annotation 格式

名稱 格式 說明
method_idx uint 索引至 method_ids 清單,找出要為參數加上註解的方法身分
annotations_off uint 從檔案開頭到方法參數註解清單的位移。偏移量應指向 data 部分中的位置。資料格式由「annotation_set_ref_list」指定,如下所示: "annotation_set_ref_list"。

annotation_set_ref_list

參照自 parameter_annotations_item

顯示在「資料」部分

對齊:4 個位元組

名稱 格式 說明
size uint 清單大小 (以項目為單位)
清單 annotation_set_ref_item[size] 清單中的元素

annotation_set_ref_item 格式

名稱 格式 說明
annotations_off uint 從檔案開頭到參照註解集的偏移量,如果這個元素沒有註解,則為 0。 如果偏移量不是零,則應指向 data 區段中的位置。資料格式由「annotation_set_item」指定,如下所示: "annotation_set_item"。

annotation_set_item

參照自 annotations_directory_item、field_annotations_item、 method_annotations_item 和 annotation_set_ref_item

顯示在「資料」部分

對齊:4 個位元組

名稱 格式 說明
size uint 集合大小 (以項目為單位)
entries annotation_off_item[size] 集合的元素。元素必須依 type_idx 遞增排序。

annotation_off_item 格式

名稱 格式 說明
annotation_off uint 從檔案開頭到註解的位移。 位移應指向 data 區段中的位置,而該位置的資料格式則由下方的「annotation_item」指定。

annotation_item

參照自 annotation_set_item

顯示在「資料」部分

對齊方式:無 (位元組對齊)

名稱 格式 說明
顯示設定 ubyte 這項註解的預期瀏覽權限 (請參閱下文)
Annotation encoded_annotation 編碼的註解內容,格式如上文「encoded_value 編碼」下的「encoded_annotation 格式」所述。

瀏覽權限值

以下是 annotation_itemvisibility 欄位的選項:

名稱 說明
VISIBILITY_BUILD 0x00 僅供在建構時顯示 (例如在編譯其他程式碼時)
VISIBILITY_RUNTIME 0x01 在執行階段顯示
VISIBILITY_SYSTEM 0x02 預計在執行階段顯示,但僅限於基礎系統 (而非一般使用者程式碼)

encoded_array_item

參照自 class_def_item

顯示在「資料」部分

對齊方式:無 (位元組對齊)

名稱 格式 說明
encoded_array 代表編碼陣列值的位元組,格式如上述「encoded_value編碼」下方「encoded_array格式」所指定。

hiddenapi_class_data_item

這個部分包含每個類別使用的受限介面資料。

注意: Android 10.0 導入了隱藏 API 功能,且僅適用於啟動類別路徑中類別的 DEX 檔案。 日後發布的 Android 版本可能會擴充下文所述的旗標清單。詳情請參閱「非 SDK 介面的相關限制」。

名稱 格式 說明
size uint 區段總大小
抵銷 uint[] class_idx 編入索引的位移陣列。 索引 class_idx 的零陣列項目表示這個 class_idx 沒有資料,或是所有隱藏的 API 旗標都是零。否則陣列項目為非零值,且包含從區段開頭到這個 class_idx 的隱藏 API 旗標陣列的偏移。
flag uleb128[] 每個類別的隱藏 API 旗標串連陣列。 下表說明可能的旗標值。 旗標的編碼順序與類別資料中欄位和方法的編碼順序相同。

限制標記類型:

名稱 說明
白名單 0 可自由使用的介面,現已列入 Android 架構「套件索引」中正式記錄的項目並獲得支援。
可疑項目清單 1 無論應用程式的目標 API 級別為何,都可以使用的非 SDK 介面。
列入黑名單 2 無論應用程式的目標 API 級別為何,都無法使用的非 SDK 介面。存取這些介面時會導致執行階段錯誤
greylist‑max‑o 3 除非受到限制,否則可用於 Android 8.x 以下版本的非 SDK 介面。
greylist‑max‑p 4 除非受到限制,否則可搭配 Android 9.x 使用的非 SDK 介面。
greylist‑max‑q 5 除非受到限制,否則可供 Android 10.x 使用的非 SDK 介面。
greylist‑max‑r 6 除非受到限制,否則可用於 Android 11.x 的非 SDK 介面。

系統註解

系統註解用於表示類別 (以及方法和欄位) 的各種反射資訊。一般來說,用戶端 (非系統) 程式碼只會間接存取這項資訊。

系統註解在 .dex 檔案中會以註解形式呈現,且可見度設為 VISIBILITY_SYSTEM

dalvik.annotation.AnnotationDefault

顯示在註解介面的方法中

AnnotationDefault 註解會附加至每個要指出預設繫結的註解介面。

名稱 格式 說明
註解 這個註解的預設繫結,以這個類型的註解表示。註解不必包含註解定義的所有名稱,缺少名稱就沒有預設值。

dalvik.annotation.EnclosingClass

顯示在課程中

EnclosingClass 註解會附加至每個類別,這些類別可以是定義為另一個類別的成員,也可以是匿名但未在方法主體中定義 (例如合成內部類別)。凡是具有此註解的類別,也必須有 InnerClass 註解。此外,類別不得同時具有 EnclosingClassEnclosingMethod 註解。

名稱 格式 說明
類別 最接近此類別的詞彙範圍的類別

dalvik.annotation.EnclosingMethod

顯示在課程中

EnclosingMethod 註解會附加至方法主體內定義的每個類別。凡是具有這項註解的類別,也必須有 InnerClass 註解。此外,類別不得同時具有 EnclosingClassEnclosingMethod 註解。

名稱 格式 說明
方法 最接近此類別詞彙範圍的方法

dalvik.annotation.InnerClass

顯示在課程中

InnerClass 註解會附加至每個類別,這些類別定義在另一個類別定義的詞彙範圍中。凡是具有此註解的類別,也必須具有 EnclosingClass 註解 EnclosingMethod 註解。

名稱 格式 說明
name 字串 這個類別原本宣告的簡單名稱 (不含任何套件前置字串)。如果這個類別是匿名,則名稱為 null
accessFlags int 類別原始宣告的存取權標記 (可能與有效標記不同,因為來源語言和目標虛擬機器的執行模型不符)

dalvik.annotation.MemberClasses

顯示在課程中

每個宣告成員類別的類別都會附加 MemberClasses 註解。(成員類別是具有名稱的直接內部類別)。

名稱 格式 說明
Class[] 成員類別陣列

dalvik.annotation.MethodParameters

顯示方法

注意:這項註解是在 Android 7.1 之後新增。如果出現在舊版 Android 中,系統會忽略這個標記。

MethodParameters 註解為選用項目,可用於提供參數中繼資料,例如參數名稱和修飾符。

如果執行階段不需要參數中繼資料,可以放心從方法或建構函式中省略註解。java.lang.reflect.Parameter.isNamePresent() 可用於檢查參數是否有中繼資料,如果沒有,相關聯的反射方法 (例如 java.lang.reflect.Parameter.getName()) 會在執行階段回復為預設行為。

加入參數中繼資料時,編譯器必須包含所產生類別的資訊 (例如列舉),因為參數中繼資料會指出參數是否為合成或強制。

MethodParameters 註解只會說明個別方法參數。因此,為了縮減程式碼大小和提高執行階段效率,編譯器可能會完全省略沒有參數的建構函式和方法註解。

以下記錄的陣列大小必須與方法相關聯的 method_id_item dex 結構相同,否則會在執行階段擲回 java.lang.reflect.MalformedParametersException

也就是說:method_id_item.proto_idx -> proto_id_item.parameters_off -> type_list.size 必須與 names().lengthaccessFlags().length 相同。

由於 MethodParameters 會說明所有正式方法參數,即使是來源程式碼中未明確或隱含宣告的參數也包含在內,因此陣列大小可能與僅根據來源程式碼中宣告的明確參數所產生的簽章或其他中繼資料資訊不同。MethodParameters 也不會包含實際方法簽章中不存在的型別註解接收器參數相關資訊。

名稱 格式 說明
名稱 String[] 相關聯方法的正式參數名稱。陣列不得為空值,但如果沒有形式參數,則必須為空。如果該索引的正式參數沒有名稱,陣列中的值就必須為空值。
如果參數名稱字串為空白,或包含「.」、「;」、「[」或「/」,系統會在執行階段擲回 java.lang.reflect.MalformedParametersException
accessFlags int[] 相關聯方法正式參數的存取權標記。陣列不得為空值,但如果沒有正式參數,則必須為空。
這個值是位元遮罩,包含下列值:
  • 0x0010:最終,參數已宣告為最終
  • 0x1000:合成,參數是由編譯器導入
  • 0x8000:強制,參數是合成的,但語言規格也暗示了這一點
如果在這個集合之外設定任何位元,系統會在執行階段擲回 java.lang.reflect.MalformedParametersException

dalvik.annotation.Signature

顯示在類別、欄位和方法上

Signature 註解會附加至每個類別、欄位或方法,這些項目是以比 type_id_item 可表示的類型更複雜的類型定義。 .dex 格式不會定義簽章格式,只是為了能夠代表來源語言為成功實作該語言語意而要求的任何簽章。因此,虛擬機器實作通常不會剖析 (或驗證) 簽章。簽章只會移交給較高層級的 API 和工具 (例如偵錯工具)。因此,任何簽章的使用方式都應經過編寫,不得假設只會收到有效簽章,並明確防範遇到語法無效簽章的可能性。

由於簽章字串往往有許多重複內容,因此 Signature 註解會定義為字串陣列,其中重複的元素自然會參照相同的基礎資料,而簽章則視為陣列中所有字串的串連。沒有任何規則規定如何將簽章拆分成個別字串,這完全取決於產生 .dex 檔案的工具。

名稱 格式 說明
String[] 這個類別或成員的簽章,以要串聯在一起的字串陣列形式表示

dalvik.annotation.Throws

顯示方法

每個方法都會附加 Throws 註解,這些方法會宣告擲回一或多個例外狀況型別。

名稱 格式 說明
Class[] 擲回的例外狀況類型陣列