このドキュメントでは、クラス定義のセットとそれらに関連付けられた付属データを保持するために使用される .dex
ファイルのレイアウトと内容について説明します。
型のガイド
名前 | 説明 |
---|---|
byte | 8 ビットの符号付き整数 |
ubyte | 8 ビットの符号なし整数 |
short | 16 ビットの符号付き整数、リトル エンディアン |
ushort | 16 ビットの符号なし整数、リトル エンディアン |
int | 32 ビットの符号付き整数、リトル エンディアン |
uint | 32 ビットの符号なし整数、リトル エンディアン |
long | 64 ビットの符号付き整数、リトル エンディアン |
ulong | 64 ビットの符号なし整数、リトル エンディアン |
sleb128 | 符号付き LEB128、可変長(以下を参照) |
uleb128 | 符号なし LEB128、可変長(以下を参照) |
uleb128p1 | 符号なし LEB128 プラス 1 、可変長(以下を参照) |
LEB128
LEB128(Little-Endian Base 128)は、任意の符号付きまたは符号なし整数値の可変長エンコードです。形式は DWARF3 仕様から借用されたものです。.dex
ファイルでは、LEB128 は 32 ビット数値のエンコードにのみ使用されます。
LEB128 でエンコードされた値は 1~5 バイトで構成され、合わせて単一の 32 ビット値を表します。シーケンス内の各バイトでは、最終バイトのみ最上位ビットがクリアされ、それ以外のバイトの最上位ビットはセットされます。各バイトの残りの 7 ビットはペイロードであり、第 1 バイトには数値の最下位 7 ビット、第 2 バイトには次の 7 ビットというように続きます。符号付き LEB128(sleb128
)の場合、シーケンスの最終バイトの最上位ペイロード ビットが符号拡張されて最終値が生成されます。符号なし(uleb128
)の場合、明示的に表現されていないビットはすべて 0
として解釈されます。
2 バイトの LEB128 値のビット単位の図 | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
第 1 バイト | 第 2 バイト | ||||||||||||||
1 |
ビット6 | ビット5 | ビット4 | ビット3 | ビット2 | ビット1 | ビット0 | 0 |
ビット13 | ビット12 | ビット11 | ビット10 | ビット9 | ビット8 | ビット7 |
バリアントの uleb128p1
は符号付きの値を表現するために使用され、1 をプラスした値を uleb128
でエンコードして表現されます。これにより、-1
のエンコード(符号なしの値 0xffffffff
ともみなされます)は単一バイトになります(ただし、他の負数はそうなりません)。この形式は、表現される数が必ず非負または -1
(あるいは 0xffffffff
)で、他の負の値が許可されない(または符号なしの大きな値が必要とされる可能性が低い)場合に有用です。
以下に各形式の例を示します。
エンコードされたシーケンス | sleb128 の場合 |
uleb128 の場合 |
uleb128p1 の場合 |
---|---|---|---|
00 | 0 | 0 | -1 |
01 | 1 | 1 | 0 |
7f | -1 | 127 | 126 |
80 7f | -128 | 16256 | 16255 |
ファイル レイアウト
名前 | 形式 | 説明 |
---|---|---|
header | header_item | ヘッダー。 |
string_ids | string_id_item[] | 文字列識別子リスト。このファイルで使用されるすべての文字列の識別子であり、内部での命名(型記述子など)に使用されるか、コードが参照する定数オブジェクトとして使用されます。このリストは、UTF-16 のコードポイントを使用して(ロケールに依存しない方法で)文字列の内容順に並べる必要があります。重複するエントリを含めることはできません。 |
type_ids | type_id_item[] | 型識別子リスト。ファイル内で定義されているかどうかにかかわらず、このファイルにより参照されるすべての型(クラス型、配列型、またはプリミティブ型)の識別子です。このリストは string_id インデックス順に並べる必要があります。重複するエントリを含めることはできません。
|
proto_ids | proto_id_item[] | メソッド プロトタイプ識別子リスト。このファイルにより参照されるすべてのプロトタイプの識別子です。このリストは、戻り値の型(type_id インデックス順)をメジャー ソートキーとし、引数リスト(辞書順。個々の引数は type_id インデックス順)をマイナー ソートキーとして並べる必要があります。このリストに重複するエントリを含めることはできません。
|
field_ids | field_id_item[] | フィールド識別子リスト。ファイル内で定義されているかどうかにかかわらず、このファイルにより参照されるすべてのフィールドの識別子です。このリストは、定義元の型(type_id インデックス順)をメジャー ソートキー、フィールド名(string_id インデックス順)を中間ソートキー、型(type_id インデックス順)をマイナー ソートキーとして並べる必要があります。このリストに重複するエントリを含めることはできません。
|
method_ids | method_id_item[] | メソッド識別子リスト。ファイル内で定義されているかどうかにかかわらず、このファイルにより参照されるすべてのメソッドの識別子です。このリストは、定義元の型(type_id インデックス順)をメジャー ソートキー、メソッド名(string_id インデックス順)を中間ソートキー、メソッド プロトタイプ(proto_id インデックス順)をマイナー ソートキーとして並べる必要があります。このリストに重複するエントリを含めることはできません。
|
class_defs | class_def_item[] | クラス定義リスト。クラスは、各クラスのスーパークラスと実装されたインターフェースが参照元クラスより前に指定されるように並べる必要があります。また、同じ名前のクラスの定義がリスト内で重複すると、無効になります。 |
call_site_ids | call_site_id_item[] | コールサイト識別子リスト。ファイル内で定義されているかどうかにかかわらず、このファイルにより参照されるすべてのコールサイトの識別子です。このリストは call_site_off の昇順で並べる必要があります。
|
method_handles | method_handle_item[] | メソッド ハンドル リスト。ファイル内で定義されているかどうかにかかわらず、このファイルにより参照されるすべてのメソッド ハンドルのリストです。このリストは特定の順序で並べる必要がありません。また、異なるメソッド ハンドル インスタンスに論理的に対応する場合は、メソッド ハンドルが重複していても構いません。 |
data | ubyte[] | 上記の表のすべてのサポートデータを含むデータ領域。 アイテムごとに異なる位置揃えの要件があり、適切な位置揃えを行うために、必要に応じてパディング バイトが各アイテムの前に挿入されます。 |
link_data | ubyte[] | 静的にリンクされるファイル内で使用されるデータ。このセクションに含まれるデータの形式については、このドキュメントに記載していません。ファイルがリンクされていない場合、このセクションは空です。ランタイム実装では、適切と考えられる場合にこのセクションを使用できます。 |
ビットフィールド、文字列、定数の定義
DEX_FILE_MAGIC
header_item に埋め込み済み
定数の配列または文字列である DEX_FILE_MAGIC
は、.dex
ファイルとして認識されるためにファイルの先頭に配置する必要があるバイトのリストです。この値には、特定の種類の破損を検出するために、改行("\n"
または 0x0a
)と null バイト("\0"
または 0x00
)が意図的に含まれています。また、この値は、ファイル形式のバージョン番号を 3 桁の 10 進数としてエンコードします。この番号は、ファイル形式が進化するにつれて単調増加することが想定されています。
ubyte[8] DEX_FILE_MAGIC = { 0x64 0x65 0x78 0x0a 0x30 0x33 0x39 0x00 } = "dex\n039\0"
注: Android 9.0 リリースでは、ファイル形式のバージョン 039
のサポートが追加され、2 つの新しいバイトコード const-method-handle
と const-method-type
が導入されました(これらは、バイトコード セットの概要の表にそれぞれ記載されています)。Android 10 では、バージョン 039
で DEX ファイル形式が拡張され、ブート クラスパス上の DEX ファイルにのみ適用される非表示 API の情報が含まれるようになりました。
注: Android 8.0 リリースでは、ファイル形式のバージョン 038
のサポートが追加されました。バージョン 038
では新しいバイトコード(invoke-polymorphic
、invoke-custom
)とメソッド ハンドル用データが追加されました。
注: Android 7.0 リリースでは、ファイル形式のバージョン 037
のサポートが追加されました。バージョン 037
より前は、Android のほとんどのバージョンはファイル形式のバージョン 035
を使用していました。バージョン 035
とバージョン 037
の唯一の違いは、デフォルト メソッドの追加と invoke
の調整が行われている点です。
注: 広く普及している公開ソフトウェア リリースで、以前のバージョンのファイル形式が少なくとも 2 つ使用されています。たとえば、Android プラットフォームの M3 リリース(2007 年 11 月~12 月)ではバージョン 009
が使用され、Android プラットフォームの M5 リリース(2008 年 2 月~3 月)ではバージョン 013
が使用されていました。これらの古いファイル形式のバージョンでは、このドキュメントで説明しているバージョンとは大きく異なる点がいくつかあります。
ENDIAN_CONSTANT と REVERSE_ENDIAN_CONSTANT
header_item に埋め込み済み
定数 ENDIAN_CONSTANT
は、ファイル内で検出されたエンディアン形式を示すために使用されます。標準の .dex
形式はリトル エンディアンですが、実装ではバイトスワップの実行を選択できます。ヘッダーの endian_tag
が ENDIAN_CONSTANT
ではなく REVERSE_ENDIAN_CONSTANT
であると検出された実装では、想定される形式からファイルがバイトスワップされたことが認識されます。
uint ENDIAN_CONSTANT = 0x12345678; uint REVERSE_ENDIAN_CONSTANT = 0x78563412;
NO_INDEX
class_def_item と debug_info_item に埋め込み済み
定数 NO_INDEX
は、インデックス値が存在しないことを示すために使用されます。
注: この値が 0
として定義されることはありません。これが実際、一般的に有効なインデックスであるためです。
NO_INDEX
に選択される値は、uleb128p1
エンコードで単一バイトとして表現されます。
uint NO_INDEX = 0xffffffff; // == -1 if treated as a signed int
access_flags 定義
class_def_item、encoded_field、encoded_method、InnerClass に埋め込み済み
これらのフラグのビットフィールドは、クラスとクラスメンバーのアクセス可能性と全体的なプロパティを示すために使用されます。
名前 | 値 | クラス(および InnerClass アノテーション)の場合 |
フィールドの場合 | メソッドの場合 |
---|---|---|---|---|
ACC_PUBLIC | 0x1 | public : どこからでも参照可能 |
public : どこからでも参照可能 |
public : どこからでも参照可能 |
ACC_PRIVATE | 0x2 | private : 定義元のクラスからのみ参照可能
|
private : 定義元のクラスからのみ参照可能 |
private : 定義元のクラスからのみ参照可能 |
ACC_PROTECTED | 0x4 | protected : パッケージとサブクラスから参照可能
|
protected : パッケージとサブクラスから参照可能 |
protected : パッケージとサブクラスから参照可能 |
ACC_STATIC | 0x8 | static : 外部への this 参照がない |
static : 定義元のクラスからグローバルに参照可能 |
static : this 引数を取らない |
ACC_FINAL | 0x10 | final : サブクラス化不可 |
final : 作成後は変更不可 |
final : 上書き不可 |
ACC_SYNCHRONIZED | 0x20 | synchronized : このメソッドの呼び出しで自動的に取得される関連ロック。注: これは、 |
||
ACC_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
形式では、デファクト スタンダードである修正(Modified)UTF-8(以下このドキュメントでは MUTF-8 と呼びます)形式で文字列データをエンコードします。この形式は、次の点を除いて標準の UTF-8 と同じです。
- 1 バイト、2 バイト、3 バイトのエンコードのみが使用されます。
U+10000
~U+10ffff
の範囲内のコードポイントはサロゲートペアとしてエンコードされ、それぞれが 3 バイトのエンコード値として表されます。- コードポイント
U+0000
は 2 バイト形式でエンコードされます。 - 単なる null バイト(値
0
)は、標準の C 言語の解釈と同様に、文字列の終わりを示します。
前半の 2 つの項目は、次のように要約できます。すなわち、MUTF-8 は Unicode 文字の直接のエンコード形式ではなく、UTF-16 用のエンコード形式です。
後半の文字列に 2 つの項目は、コードポイント U+0000
を文字列に含められることと、同時にそれを引き続き C スタイルの null 終端文字列として扱えることを示します。
ただし、U+0000
という特殊なエンコードを使うことにより、通常の UTF-8 とは異なり、MUTF-8 文字列のペアに対して標準の C 関数 strcmp()
を呼び出した場合、等しくない文字列の比較結果に正しい符号が付かないこともあります。(等しいかどうかだけでなく)順序も問題になる場合、MUTF-8 文字列を比較する最も簡単な方法は、その文字列を文字ごとにデコードして、デコードした値を比較することです(ただし、それより高度な実装も可能です)。
文字エンコードの詳細については、Unicode 規格をご覧ください。MUTF-8 は実際には、本来の UTF-8 よりも(あまり知られていない)CESU-8 に近いエンコードです。
encoded_value エンコード
annotation_element と encoded_array_item に埋め込み済み
encoded_value
は(ほぼ)任意の階層構造化データのエンコードです。このエンコードは、コンパクトであることと解析しやすいことを目指しています。
名前 | 形式 | 説明 |
---|---|---|
(value_arg << 5) | value_type | ubyte | 直後の value の型を示すバイトで、上位 3 ビットに明示的な引数(省略可)が格納されます。各種の value の定義については、下記をご覧ください。ほとんどの場合、value_arg は直後の value の長さ(バイト数)を (size - 1) としてエンコードします。たとえば、0 は value が 1 バイトを必要とすることを意味し、7 は 8 バイトを必要とすることを意味します。ただし、後述のような例外があります。
|
value | ubyte[] | 可変長の値を表すバイト。value_type バイトに応じて異なって解釈されますが、常にリトル エンディアンです。詳細については、以下の各種の value の定義をご覧ください。
|
値の形式
型名 | value_type |
value_arg の形式 |
value の形式 |
説明 |
---|---|---|---|---|
VALUE_BYTE | 0x00 | (なし、0 であることが必要) |
ubyte[1] | 1 バイトの符号付き整数値 |
VALUE_SHORT | 0x02 | size - 1 (0…1) | ubyte[size] | 2 バイトの符号付き整数値、符号拡張あり |
VALUE_CHAR | 0x03 | size - 1 (0…1) | ubyte[size] | 2 バイトの符号なし整数値、ゼロ拡張あり |
VALUE_INT | 0x04 | size - 1 (0…3) | ubyte[size] | 4 バイトの符号付き整数値、符号拡張あり |
VALUE_LONG | 0x06 | size - 1 (0…7) | ubyte[size] | 8 バイトの符号付き整数値、符号拡張あり |
VALUE_FLOAT | 0x10 | size - 1 (0…3) | ubyte[size] | 4 バイトのビットパターン、右へのゼロ拡張あり。IEEE754 の 32 ビット浮動小数点値として解釈されます |
VALUE_DOUBLE | 0x11 | size - 1 (0…7) | ubyte[size] | 8 バイトのビットパターン、右へのゼロ拡張あり。IEEE754 の 64 ビット浮動小数点値として解釈されます |
VALUE_METHOD_TYPE | 0x15 | size - 1 (0…3) | ubyte[size] | 4 バイトの符号なし(ゼロ拡張)整数値。proto_ids セクションに対するインデックスとして解釈され、メソッド型の値を表します
|
VALUE_METHOD_HANDLE | 0x16 | size - 1 (0…3) | ubyte[size] | 4 バイトの符号なし(ゼロ拡張)整数値。method_handles セクションに対するインデックスとして解釈され、メソッド ハンドル値を表します
|
VALUE_STRING | 0x17 | size - 1 (0…3) | ubyte[size] | 4 バイトの符号なし(ゼロ拡張)整数値。string_ids セクションに対するインデックスとして解釈され、文字列値を表します
|
VALUE_TYPE | 0x18 | size - 1 (0…3) | ubyte[size] | 4 バイトの符号なし(ゼロ拡張)整数値。type_ids セクションに対するインデックスとして解釈され、リフレクティブ型 / クラス値を表します
|
VALUE_FIELD | 0x19 | size - 1 (0…3) | ubyte[size] | 4 バイトの符号なし(ゼロ拡張)整数値。field_ids セクションに対するインデックスとして解釈され、リフレクティブ フィールド値を表します
|
VALUE_METHOD | 0x1a | size - 1 (0…3) | ubyte[size] | 4 バイトの符号なし(ゼロ拡張)整数値。method_ids セクションに対するインデックスとして解釈され、リフレクティブ メソッド値を表します
|
VALUE_ENUM | 0x1b | size - 1 (0…3) | ubyte[size] | 4 バイトの符号なし(ゼロ拡張)整数値。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 | boolean (0…1) | (なし) | 1 ビットの値。0 は false 、1 は true を表します。ビットは value_arg で表されます
|
encoded_array の形式
名前 | 形式 | 説明 |
---|---|---|
size | uleb128 | 配列内の要素数。 |
values | encoded_value[size] | このセクションで規定されている形式の、順番に連結された一連の size の encoded_value バイト シーケンス。
|
encoded_annotation の形式
名前 | 形式 | 説明 |
---|---|---|
type_idx | uleb128 | アノテーションの型。(配列型でもプリミティブ型でもなく)クラス型であること。 |
size | uleb128 | このアノテーション内の名前 / 値マッピングの数。 |
elements | annotation_element[size] | (オフセットとしてではなく)インラインで直接表される、アノテーションの要素。要素は string_id インデックスの昇順で並べる必要があります。
|
annotation_element の形式
名前 | 形式 | 説明 |
---|---|---|
name_idx | uleb128 | string_ids セクションに対するインデックスとして表される要素名。文字列は、上記で定義されている MemberName の構文に従う必要があります。
|
value | encoded_value | 要素の値。 |
文字列の構文
.dex
ファイル内には、最終的には文字列を参照する数種類のアイテムがあります。以下の BNF スタイルの定義は、そうした文字列に使用できる構文を示します。
SimpleName
SimpleName は、他のアイテム名の構文に対して基礎となります。.dex
形式では、名前についてかなり(一般的なソース言語のほとんどよりもはるかに)自由度があります。簡単に言うと、SimpleName は、任意の low-ASCII 英数字、いくつかの low-ASCII 特殊記号、ほとんどの非 ASCII コードポイント(制御文字、スペース、特殊文字を除く)で構成されます。バージョン 040
以降、この形式にスペース文字(Unicode の Zs
カテゴリ)も許容されるようになりました。サロゲート コードポイント(U+d800
~U+dfff
の範囲内)は本来有効な名前文字とみなされませんが、Unicode 補助文字は有効です(SimpleNameChar の最終代替ルールで表されます)。これを使用する場合は、ファイル内で MUTF-8 エンコードのサロゲート コードポイントのペアとして表す必要があります。
SimpleName → | ||
SimpleNameChar (SimpleNameChar)* | ||
SimpleNameChar → | ||
'A' … 'Z' |
||
| | 'a' … 'z' |
|
| | '0' … '9' |
|
| | ' ' |
DEX バージョン 040 以降 |
| | '$' |
|
| | '-' |
|
| | '_' |
|
| | U+00a0 |
DEX バージョン 040 以降 |
| | U+00a1 … U+1fff |
|
| | U+2000 … U+200a |
DEX バージョン 040 以降 |
| | U+2010 … U+2027 |
|
| | U+202f |
DEX バージョン 040 以降 |
| | U+2030 … U+d7ff |
|
| | U+e000 … U+ffef |
|
| | U+10000 … U+10ffff |
MemberName
field_id_item と method_id_item で使用
MemberName はクラスのメンバーの名前です。メンバーはフィールド、メソッド、内部クラスです。
MemberName → | |
SimpleName | |
| | '<' SimpleName '>' |
FullClassName
FullClassName は完全修飾クラス名です。パッケージ指定子(省略可)の後に必須の名前が続きます。
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 |
S | short |
C | char |
I | int |
J | long |
F | float |
D | double |
Lfully/qualified/Name; | クラス fully.qualified.Name |
[descriptor | descriptor の配列(配列の配列で再帰的に使用できますが、255 個を超えるディメンションは無効です)
|
アイテムと関連構造
このセクションでは、.dex
ファイルで使用できる最上位アイテムを定義します。
header_item
header セクションで指定
位置揃え: 4 バイト
名前 | 形式 | 説明 |
---|---|---|
magic | ubyte[8] = DEX_FILE_MAGIC | マジック値。詳細については、上記の「DEX_FILE_MAGIC 」の説明をご覧ください。
|
checksum | uint | ファイルの残り(magic とこのフィールド以外のすべて)の adler32 チェックサム。ファイルの破損を検出するために使用されます。
|
signature | ubyte[20] | ファイルの残り(magic 、checksum とこのフィールド以外のすべて)の SHA-1 署名(ハッシュ)。ファイルを一意に識別するために使用されます。
|
file_size | uint | ファイル全体(ヘッダーを含む)のサイズ(バイト数) |
header_size | uint = 0x70 | ヘッダー(このセクション全体)のサイズ(バイト数)。これによって、形式を無効にせずに最低限の限定的な下位互換性 / 上位互換性を確保できます。 |
endian_tag | uint = ENDIAN_CONSTANT | エンディアン形式タグ。詳細については、上記の「ENDIAN_CONSTANT と REVERSE_ENDIAN_CONSTANT 」の説明をご覧ください。
|
link_size | uint | リンク セクションのサイズ。このファイルが静的にリンクされていない場合は 0 。 |
link_off | uint | ファイルの先頭からリンク セクションまでのオフセット。link_size == 0 の場合は 0 。このオフセットは、ゼロでない場合、link_data セクションまでのオフセットとします。リンク先のデータの形式は、このドキュメントでは規定していません。このヘッダー フィールド(と前のフィールド)は、ランタイム実装で使用されるフックとして残されます。
|
map_off | uint | ファイルの先頭からマップアイテムまでのオフセット。このオフセットはゼロ以外の値で、data セクションまでのオフセットとします。データは下記の「map_list 」で規定されている形式とします。
|
string_ids_size | uint | 文字列識別子リスト内の文字列の数。 |
string_ids_off | uint | ファイルの先頭から文字列識別子リストまでのオフセット。string_ids_size == 0 (明らかに奇妙なエッジケース)の場合は 0 。このオフセットは、ゼロでない場合、string_ids セクションの先頭までのオフセットとします。
|
type_ids_size | uint | 型識別子リスト内の要素の数。最大で 65535。 |
type_ids_off | uint | ファイルの先頭から型識別子リストまでのオフセット。type_ids_size == 0 (明らかに奇妙なエッジケース)の場合は 0 。このオフセットは、ゼロでない場合、type_ids セクションの先頭までのオフセットとします。
|
proto_ids_size | uint | プロトタイプ識別子リスト内の要素の数。最大で 65535。 |
proto_ids_off | uint | ファイルの先頭からプロトタイプ識別子リストまでのオフセット。proto_ids_size == 0 (明らかに奇妙なエッジケース)の場合は 0 。このオフセットは、ゼロでない場合、proto_ids セクションの先頭までのオフセットとします。
|
field_ids_size | uint | フィールド識別子リスト内の要素の数。 |
field_ids_off | uint | ファイルの先頭からフィールド識別子リストまでのオフセット。field_ids_size == 0 の場合は 0 。このオフセットは、ゼロでない場合、field_ids セクションの先頭までのオフセットとします。
|
method_ids_size | uint | メソッド識別子リスト内の要素の数。 |
method_ids_off | uint | ファイルの先頭からメソッド識別子リストまでのオフセット。method_ids_size == 0 の場合は 0 。このオフセットは、ゼロでない場合、method_ids セクションの先頭までのオフセットとします。
|
class_defs_size | uint | クラス定義リスト内の要素の数。 |
class_defs_off | uint | ファイルの先頭からクラス定義リストまでのオフセット。class_defs_size == 0 (明らかに奇妙なエッジケース)の場合は 0 。このオフセットは、ゼロでない場合、class_defs セクションの先頭までのオフセットとします。
|
data_size | uint | data セクションのサイズ(バイト数)。sizeof(uint) の偶数倍でなければなりません。 |
data_off | uint | ファイルの先頭から data セクションの先頭までのオフセット。
|
map_list
data セクションで指定
header_item から参照
位置揃え: 4 バイト
これは、ファイルの内容全体を順番に並べたリストです。header_item
については冗長性が多少含まれますが、ファイル全体を反復処理しやすい形式を意図しています。各型をマップ内で指定できるのは最大 1 回ですが、残りの形式によって暗黙的に規定される制限(たとえば header
セクションが最初に来てその後に string_ids
セクションが続くなど)を除き、型を指定する順序に制限はありません。また、マップエントリは最初のオフセット順に並べる必要があり、重複を含めることはできません。
名前 | 形式 | 説明 |
---|---|---|
size | uint | リストのサイズ(エントリ数) |
list | map_item[size] | リストの要素 |
map_item の形式
名前 | 形式 | 説明 |
---|---|---|
type | ushort | アイテムの型。下の表を参照 |
unused | ushort | (不使用) |
size | uint | 指定されたオフセットで見つかるアイテム数 |
offset | 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
data セクションで指定
位置揃え: なし(バイト整列済み)
名前 | 形式 | 説明 |
---|---|---|
utf16_size | uleb128 | UTF-16 コードユニットで表した、この文字列のサイズ(多くのシステムでは「文字列長」)。つまり、文字列のデコードされた長さです(エンコードされた長さは 0 バイトの位置によって暗黙的に指定されます)。 |
data | ubyte[] | 一連の MUTF-8 コードユニット(オクテット、バイトとも呼ばれます)と、それに続く 1 バイトの 0 値。このデータ形式の詳細な説明については、上記の「MUTF-8(Modified UTF-8)エンコード」をご覧ください。
注: Unicode の UTF-16 への通常のエンコードとは無関係の、または順不同の、UTF-16 サロゲート コードユニット( |
type_id_item
type_ids セクションで指定
位置揃え: 4 バイト
名前 | 形式 | 説明 |
---|---|---|
descriptor_idx | uint | この型の記述子文字列の string_ids リストに対するインデックス。文字列は、上記で定義されている TypeDescriptor の構文に従う必要があります。
|
proto_id_item
proto_ids セクションで指定
位置揃え: 4 バイト
名前 | 形式 | 説明 |
---|---|---|
shorty_idx | uint | このプロトタイプの短縮形記述子文字列の string_ids リストに対するインデックス。文字列は、上記で定義されている ShortyDescriptor の構文に従い、このアイテムの戻り値の型とパラメータに対応する必要があります。
|
return_type_idx | uint | このプロトタイプの戻り値の型の type_ids リストに対するインデックス。 |
parameters_off | uint | ファイルの先頭からこのプロトタイプのパラメータ型のリストまでのオフセット。このプロトタイプにパラメータがない場合は 0 。このオフセットは、ゼロでない場合、data セクション内で指定し、そこにあるデータは下記の "type_list" で規定されている形式に従う必要があります。また、リスト内の型 void への参照を含めることはできません。
|
field_id_item
field_ids セクションで指定
位置揃え: 4 バイト
名前 | 形式 | 説明 |
---|---|---|
class_idx | ushort | このフィールドの定義元の type_ids リストに対するインデックス。配列型またはプリミティブ型ではなく、クラス型であることが必要です。
|
type_idx | ushort | このフィールドの型の type_ids リストに対するインデックス。 |
name_idx | uint | このフィールドの名前の string_ids リストに対するインデックス。文字列は、上記で定義されている MemberName の構文に従う必要があります。
|
method_id_item
method_ids セクションで指定
位置揃え: 4 バイト
名前 | 形式 | 説明 |
---|---|---|
class_idx | ushort | このメソッドの定義元の type_ids リストに対するインデックス。プリミティブ型ではなく、クラス型または配列型であることが必要です。
|
proto_idx | ushort | このメソッドのプロトタイプの proto_ids リストに対するインデックス。 |
name_idx | uint | このメソッドの名前の string_ids リストに対するインデックス。文字列は、上記で定義されている MemberName の構文に従う必要があります。
|
class_def_item
class_defs セクションで指定
位置揃え: 4 バイト
名前 | 形式 | 説明 |
---|---|---|
class_idx | uint | このクラスの type_ids リストに対するインデックス。配列型またはプリミティブ型ではなく、クラス型であることが必要です。
|
access_flags | uint | クラスのアクセスフラグ(public 、final など)。詳細については、「access_flags 定義」をご覧ください。
|
superclass_idx | uint | スーパークラスの type_ids リストに対するインデックス。このクラスにスーパークラスがない場合(つまり、Object などのルートクラスである場合)は定数値 NO_INDEX 。存在する場合は、配列型またはプリミティブ型ではなく、クラス型であることが必要です。
|
interfaces_off | uint | ファイルの先頭からインターフェースのリストまでのオフセット。存在しない場合は 0 。このオフセットは data セクション内に存在しなければならず、データは下記の「type_list 」で規定される形式に従う必要があります。リストの各要素は(配列型またはプリミティブ型ではなく)クラス型であることが必要です。重複を含めることはできません。
|
source_file_idx | uint | このクラスの(少なくとも大多数の)元のソースが含まれるファイルの名前の string_ids リストに対するインデックス。または、その情報の欠落を表す特別な値 NO_INDEX 。任意のメソッドの debug_info_item でこのソースファイルをオーバーライドできますが、ほとんどのクラスは 1 つのソースファイルに由来することが期待されます。
|
annotations_off | uint | ファイルの先頭からこのクラスのアノテーション構造体までのオフセット。このクラスにアノテーションがない場合は 0 。このオフセットは、ゼロでない場合、data セクション内で指定しなければならず、そこにあるデータは下記の「annotations_directory_item 」で規定されている形式に従う必要があります。また、すべてのアイテムはこのクラスを定義元として参照する必要があります。
|
class_data_off | uint | ファイルの先頭からこのアイテムの関連クラスデータまでのオフセット。このクラスのクラスデータがない場合は 0 (たとえば、このクラスがマーカー インターフェースである場合)。このオフセットは、ゼロでない場合、data セクション内で指定しなければならず、そこにあるデータは下記の「class_data_item 」で規定されている形式に従う必要があります。また、すべてのアイテムはこのクラスを定義元として参照する必要があります。
|
static_values_off | uint | ファイルの先頭から static フィールドの初期値リストまでのオフセット。存在しない(かつすべての static フィールドが 0 または null で初期化される)場合は 0 。このオフセットは data セクション内で指定しなければならず、そこにあるデータは下記の「encoded_array_item 」で規定されている形式に従う必要があります。配列のサイズはこのクラスで宣言される static フィールドの数を超えてはならず、要素は対応する field_list 内で宣言されるのと同じ順序で static フィールドに対応する必要があります。各配列要素の型は、それに対応するフィールドの宣言された型と一致する必要があります。配列内の要素の数が static フィールドの数より少ない場合、余ったフィールドは型に応じて 0 または null で初期化されます。
|
call_site_id_item
call_site_ids セクションで指定
位置揃え: 4 バイト
名前 | 形式 | 説明 |
---|---|---|
call_site_off | uint | ファイルの先頭からコールサイト定義までのオフセット。このオフセットは data セクション内で指定しなければならず、そこにあるデータは下記の「call_site_item」で規定されている形式に従う必要があります。 |
call_site_item
data セクションで指定
位置揃え: なし(バイト整列済み)
call_site_item は、要素がブートストラップ リンカー メソッドに渡される引数に対応する encoded_array_item です。最初の 3 つの引数は次のとおりです。
- ブートストラップ リンカー メソッドを表すメソッド ハンドル(VALUE_METHOD_HANDLE)。
- ブート ストラップ リンカーが解決する必要があるメソッド名(VALUE_STRING)。
- 解決するメソッド名の型に対応するメソッド型(VALUE_METHOD_TYPE)。
その他のすべての引数は、ブートストラップ リンカー メソッドに渡される定数値です。これらの引数は、型変換なしで順番に渡されます。
ブートストラップ リンカー メソッドを表すメソッド ハンドルの戻り値は java.lang.invoke.CallSite
型とする必要があります。最初の 3 つのパラメータ型は次のとおりです。
java.lang.invoke.Lookup
java.lang.String
java.lang.invoke.MethodType
その他のすべての引数のパラメータ型は、その定数値から決定されます。
method_handle_item
method_handles セクションで指定
位置揃え: 4 バイト
名前 | 形式 | 説明 |
---|---|---|
method_handle_type | ushort | メソッド ハンドルの型(下記の表を参照) |
unused | ushort | (不使用) |
field_or_method_id | ushort | メソッド ハンドル型がアクセサであるかメソッド呼び出し元であるかに応じて、フィールド ID またはメソッド ID |
unused | ushort | (不使用) |
メソッド ハンドル型のコード
定数 | 値 | 説明 |
---|---|---|
METHOD_HANDLE_TYPE_STATIC_PUT | 0x00 | メソッド ハンドルは静的フィールド セッター(アクセサ)です |
METHOD_HANDLE_TYPE_STATIC_GET | 0x01 | メソッド ハンドルは静的フィールド ゲッター(アクセサ)です |
METHOD_HANDLE_TYPE_INSTANCE_PUT | 0x02 | メソッド ハンドルはインスタンス フィールド セッター(アクセサ)です |
METHOD_HANDLE_TYPE_INSTANCE_GET | 0x03 | メソッド ハンドルはインスタンス フィールド ゲッター(アクセサ)です |
METHOD_HANDLE_TYPE_INVOKE_STATIC | 0x04 | メソッド ハンドルは静的メソッドの呼び出し元です |
METHOD_HANDLE_TYPE_INVOKE_INSTANCE | 0x05 | メソッド ハンドルはインスタンス メソッドの呼び出し元です |
METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR | 0x06 | メソッド ハンドルはコンストラクタ メソッドの呼び出し元です |
METHOD_HANDLE_TYPE_INVOKE_DIRECT | 0x07 | メソッド ハンドルはダイレクト メソッドの呼び出し元です |
METHOD_HANDLE_TYPE_INVOKE_INTERFACE | 0x08 | メソッド ハンドルはインターフェース メソッドの呼び出し元です |
class_data_item
class_def_item から参照
data セクションで指定
位置揃え: なし(バイト整列済み)
名前 | 形式 | 説明 |
---|---|---|
static_fields_size | uleb128 | このアイテムに定義されている静的フィールドの数。 |
instance_fields_size | uleb128 | このアイテムに定義されているインスタンス フィールドの数。 |
direct_methods_size | uleb128 | このアイテムに定義されているダイレクト メソッドの数 |
virtual_methods_size | uleb128 | このアイテムに定義されている仮想メソッドの数。 |
static_fields | encoded_field[static_fields_size] | エンコードされた要素のシーケンスとして表される、定義済みの静的フィールド。フィールドは field_idx の昇順で並べる必要があります。
|
instance_fields | encoded_field[instance_fields_size] | エンコードされた要素のシーケンスとして表される、定義済みのインスタンス フィールド。フィールドは field_idx の昇順で並べる必要があります。
|
direct_methods | encoded_method[direct_methods_size] | エンコードされた要素のシーケンスとして表される、定義済みのダイレクト(static 、private 、コンストラクタのいずれかの)メソッド。メソッドは method_idx の昇順で並べる必要があります。
|
virtual_methods | encoded_method[virtual_methods_size] | エンコードされた要素のシーケンスとして表される、定義済みの仮想(static 、private 、コンストラクタのいずれでもない)メソッド。このアイテムが表すクラスによってオーバーライドされない限り、継承されたメソッドをこのリストに含めることはできません。メソッドは method_idx の昇順で並べる必要があります。
仮想メソッドの method_idx は、いかなるダイレクト メソッドとも同じにすることはできません。 |
注: すべての要素の field_id
と method_id
のインスタンスは、同じ定義元クラスを参照する必要があります。
encoded_field の形式
名前 | 形式 | 説明 |
---|---|---|
field_idx_diff | uleb128 | このフィールドの識別情報(名前と記述子を含む)の field_ids リストに対するインデックス。リスト内にある前の要素のインデックスとの差異として表されます。リスト内にある最初の要素のインデックスは直接表されます。
|
access_flags | uleb128 | フィールドのアクセスフラグ(public 、final など)。詳細については、「access_flags 定義」をご覧ください。
|
encoded_method の形式
名前 | 形式 | 説明 |
---|---|---|
method_idx_diff | uleb128 | このメソッドの識別情報(名前と記述子を含む)の method_ids リストに対するインデックス。リスト内にある前の要素のインデックスとの差異として表されます。リスト内にある最初の要素のインデックスは直接表されます。
|
access_flags | uleb128 | メソッドのアクセスフラグ(public 、final など)。詳細については、「access_flags 定義」をご覧ください。
|
code_off | uleb128 | ファイルの先頭からこのメソッドのコード構造体までのオフセット。このメソッドが abstract または native である場合は 0 。このオフセットは、data セクション内の位置までとする必要があります。データの形式は下記の「code_item 」で規定されます。
|
type_list
class_def_item と proto_id_item から参照
data セクションで指定
位置揃え: 4 バイト
名前 | 形式 | 説明 |
---|---|---|
size | uint | リストのサイズ(エントリ数) |
list | type_item[size] | リストの要素 |
type_item の形式
名前 | 形式 | 説明 |
---|---|---|
type_idx | ushort | type_ids リストに対するインデックス |
code_item
encoded_method から参照
data セクションで指定
位置揃え: 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 の配列として定義されますが、一部の内部構造体では 4 バイトの位置揃えが優先されることにご注意ください。また、この配列がエンディアンでスワップされたファイル内にある場合、スワップは個々の ushort でのみ行われ、大きな内部構造体では行われません。
|
padding | ushort(省略可) = 0 | 2 バイトのパディングにより、tries は 4 バイトに揃えられます。
この要素は、tries_size がゼロ以外で insns_size が奇数の場合にのみ存在します。
|
tries | try_item[tries_size](省略可) | コード例外がキャッチされた場所とその処理方法を示す配列。配列の要素は、範囲が重複せず、アドレスの低い順に並んでいる必要があります。この要素は、tries_size がゼロ以外の場合にのみ存在します。
|
handlers | 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 | このリストのサイズ(エントリ数)。 |
list | encoded_catch_handler[handlers_size] | ハンドラリストの実際のリスト。(オフセットとしてではなく)直接表され、順番に連結されます。 |
encoded_catch_handler の形式
名前 | 形式 | 説明 |
---|---|---|
size | sleb128 | このリスト内のキャッチタイプの数。正数でない場合、この値はキャッチタイプ数の負数で、キャッチの後にキャッチオール ハンドラが続きます。たとえば、size が 0 の場合は、キャッチオールが存在しますが、明示的に型付けされたキャッチが存在しないことを意味します。size が 2 の場合は、明示的に型付けされたキャッチが 2 つ存在し、キャッチオールが存在しないことを意味します。size が -1 の場合は、型付けされたキャッチが 1 つと、キャッチオールが存在することを意味します。
|
handlers | encoded_type_addr_pair[abs(size)] | abs(size) でエンコードされたアイテムのストリーム。アイテムは型がテストされる順序で、キャッチタイプにつき 1 つずつ存在します。
|
catch_all_addr | uleb128(省略可) | キャッチオール ハンドラのバイトコード アドレス。この要素は、size が正数でない場合にのみ存在します。
|
encoded_type_addr_pair の形式
名前 | 形式 | 説明 |
---|---|---|
type_idx | uleb128 | キャッチする例外の型の type_ids リストに対するインデックス
|
addr | uleb128 | 関連する例外ハンドラのバイトコード アドレス |
debug_info_item
code_item から参照
data セクションで指定
位置揃え: なし(バイト整列済み)
個々の debug_info_item
は、DWARF3 に基づいてバイトコード化されたステートマシンを定義します。このマシンは、解釈されると、code_item
のポジション表と(ある場合は)ローカル変数情報を出力します。シーケンスは可変長のヘッダー(その長さはメソッド パラメータの数で決まります)で始まり、その後にステートマシンのバイトコードが続き、DBG_END_SEQUENCE
バイトで終わります。
ステートマシンは 5 つのレジスタで構成されます。address
レジスタは、関連する insns_item
内の命令オフセットを 16 ビットコード単位で表します。address
レジスタの値は、個々の debug_info
シーケンスの先頭で 0
から始まり、単調増加します。line
レジスタは、ステートマシンが出力する次のポジション表エントリに関連付ける必要があるソース行番号を表します。これはシーケンス ヘッダー内で初期化され、正または負の方向に変更できますが、1
より小さくすることはできません。source_file
レジスタは、行番号エントリが参照するソースファイルを表します。これは class_def_item
の source_file_idx
の値に初期化されます。他の 2 つの変数 prologue_end
と epilogue_begin
はブール値のフラグです(false
に初期化されます)。出力される次のポジションをメソッドのプロローグまたはエピローグのどちらとみなすかを示します。また、ステートマシンは、DBG_RESTART_LOCAL
コードの各レジスタにライブ状態で存在する最後のローカル変数の名前と型をトラッキングする必要があります。
ヘッダーは次のとおりです。
名前 | 形式 | 説明 |
---|---|---|
line_start | uleb128 | ステートマシンの line レジスタの初期値。実際のポジション エントリを表してはいません。
|
parameters_size | uleb128 | エンコードされたパラメータ名の数。インスタンス メソッドの this (ある場合)を除いて、メソッド パラメータごとに 1 つ存在する必要があります。
|
parameter_names | uleb128p1[parameters_size] | メソッド パラメータ名の文字列インデックス。エンコードされた値 NO_INDEX は、関連パラメータに使用できる名前がないことを示します。型の記述子とシグネチャは、メソッドの記述子とシグネチャから暗黙的に指定されます。
|
バイトコードの値は次のとおりです。
名前 | 値 | 形式 | 引数 | 説明 |
---|---|---|---|---|
DBG_END_SEQUENCE | 0x00 | (なし) | code_item のデバッグ情報シーケンスを終了します。 |
|
DBG_ADVANCE_PC | 0x01 | uleb128 addr_diff | addr_diff : アドレス レジスタに追加する数値 |
ポジション エントリを出力せずにアドレス レジスタを進めます。 |
DBG_ADVANCE_LINE | 0x02 | sleb128 line_diff | line_diff : 行レジスタを変更する数値 |
ポジション エントリを出力せずに行レジスタを進めます。 |
DBG_START_LOCAL | 0x03 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx |
register_num : ローカル変数が含まれるレジスタname_idx : 名前の文字列インデックスtype_idx : 型の型インデックス
|
現在のアドレスにローカル変数を挿入します。name_idx または type_idx のいずれかが NO_INDEX の場合、その値が不明であることを示します。
|
DBG_START_LOCAL_EXTENDED | 0x04 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx uleb128p1 sig_idx |
register_num : ローカル変数が含まれるレジスタname_idx : 名前の文字列インデックスtype_idx : 型の型インデックスsig_idx : 型シグネチャの文字列インデックス
|
現在のアドレスに型シグネチャを持つローカル変数を挿入します。
name_idx 、type_idx 、sig_idx のいずれかが NO_INDEX の場合、その値が不明であることを示します(ただし、sig_idx が -1 の場合は、オペコード DBG_START_LOCAL を使用して同じデータをより効率よく表せます)。
注: シグネチャの処理に関する注意事項については、下記の「 |
DBG_END_LOCAL | 0x05 | uleb128 register_num | register_num : ローカル変数が含まれるレジスタ |
現在のアドレスで、現在ライブ状態のローカル変数をスコープ外としてマークします。 |
DBG_RESTART_LOCAL | 0x06 | uleb128 register_num | register_num : 再開するレジスタ |
現在のアドレスにローカル変数を再度挿入します。名前と型は、指定されたレジスタにライブ状態で存在していた最後のローカル変数と同じです。 |
DBG_SET_PROLOGUE_END | 0x07 | (なし) | prologue_end ステートマシンのレジスタを設定し、追加される次のポジション エントリをメソッド プロローグの終わり(メソッド ブレークポイントに適した場所)とみなすことを示します。prologue_end レジスタは、任意の特殊な(>= 0x0a の)オペコードでクリアされます。
|
|
DBG_SET_EPILOGUE_BEGIN | 0x08 | (なし) | epilogue_begin ステートマシンのレジスタを設定し、追加される次のポジション エントリをメソッド エピローグの始まり(メソッドの終了前に実行を中断するのに適した場所)とみなすことを示します。epilogue_begin レジスタは、任意の特殊な(>= 0x0a の)オペコードでクリアされます。
|
|
DBG_SET_FILE | 0x09 | uleb128p1 name_idx | name_idx : ソースファイル名の文字列インデックス。不明な場合は NO_INDEX
|
後続のすべての行番号エントリが、code_item で指定されたデフォルト名ではなく、このソースファイル名を参照することを示します。
|
特殊なオペコード | 0x0a…0xff | (なし) | line レジスタと address レジスタを進め、ポジション エントリを出力して、prologue_end と epilogue_begin をクリアします。詳細については下記をご覧ください。
|
特殊なオペコード
0x0a
から 0xff
までの値を持つオペコードは、line
レジスタと address
レジスタの両方を少しだけ移動し、新しいポジション表エントリを出力します。増分の式は次のとおりです。
DBG_FIRST_SPECIAL = 0x0a // the smallest special opcode DBG_LINE_BASE = -4 // the smallest line number increment DBG_LINE_RANGE = 15 // the number of line increments represented adjusted_opcode = opcode - DBG_FIRST_SPECIAL line += DBG_LINE_BASE + (adjusted_opcode % DBG_LINE_RANGE) address += (adjusted_opcode / DBG_LINE_RANGE)
annotations_directory_item
class_def_item から参照
data セクションで指定
位置揃え: 4 バイト
名前 | 形式 | 説明 |
---|---|---|
class_annotations_off | uint | ファイルの先頭からクラスで直接作成されたアノテーションまでのオフセット。クラスに直接のアノテーションがない場合は 0 。このオフセットは、ゼロでない場合、data セクション内の位置までとする必要があります。データの形式は下記の「annotation_set_item 」で規定されます。
|
fields_size | uint | このアイテムによってアノテーションを付けられたフィールドの数。 |
annotated_methods_size | uint | このアイテムによってアノテーションを付けられたメソッドの数。 |
annotated_parameters_size | uint | このアイテムによってアノテーションを付けられたメソッド パラメータ リストの数。 |
field_annotations | field_annotation[fields_size](省略可) | 関連付けられたフィールド アノテーションのリスト。リストの要素は field_idx の昇順で並べる必要があります。
|
method_annotations | method_annotation[methods_size](省略可) | 関連付けられたメソッド アノテーションのリスト。リストの要素は method_idx の昇順で並べる必要があります。
|
parameter_annotations | parameter_annotation[parameters_size](省略可) | 関連付けられたメソッド パラメータ アノテーションのリスト。リストの要素は method_idx の昇順で並べる必要があります。
|
注: すべての要素の field_id
と method_id
のインスタンスは、同じ定義元クラスを参照する必要があります。
field_annotation の形式
名前 | 形式 | 説明 |
---|---|---|
field_idx | uint | アノテーションが付けられたフィールドの識別情報の field_ids リストに対するインデックス。
|
annotations_off | uint | ファイルの先頭からフィールドのアノテーションのリストまでのオフセット。このオフセットは、data セクション内の位置までとする必要があります。データの形式は下記の「annotation_set_item 」で規定されます。
|
method_annotation の形式
名前 | 形式 | 説明 |
---|---|---|
method_idx | uint | アノテーションが付けられたメソッドの識別情報の method_ids リストに対するインデックス。 |
annotations_off | uint | ファイルの先頭からメソッドのアノテーションのリストまでのオフセット。このオフセットは、data セクション内の位置までとする必要があります。データの形式は下記の「annotation_set_item 」で規定されます。
|
parameter_annotation の形式
名前 | 形式 | 説明 |
---|---|---|
method_idx | uint | パラメータにアノテーションが付けられたメソッドの識別情報の method_ids リストに対するインデックス。
|
annotations_off | uint | ファイルの先頭からメソッド パラメータのアノテーションのリストまでのオフセット。このオフセットは、data セクション内の位置までとする必要があります。データの形式は下記の「annotation_set_ref_list 」で規定されます。
|
annotation_set_ref_list
parameter_annotations_item から参照
data セクションで指定
位置揃え: 4 バイト
名前 | 形式 | 説明 |
---|---|---|
size | uint | リストのサイズ(エントリ数) |
list | annotation_set_ref_item[size] | リストの要素 |
annotation_set_ref_item の形式
名前 | 形式 | 説明 |
---|---|---|
annotations_off | uint | ファイルの先頭から参照先アノテーション セットまでのオフセット。この要素にアノテーションが存在しない場合は 0 。このオフセットは、ゼロでない場合、data セクション内の位置までとする必要があります。データの形式は下記の「annotation_set_item 」で規定されます。
|
annotation_set_item
annotations_directory_item、field_annotations_item、method_annotations_item、annotation_set_ref_item から参照
data セクションで指定
位置揃え: 4 バイト
名前 | 形式 | 説明 |
---|---|---|
size | uint | セットのサイズ(エントリ数)。 |
entries | annotation_off_item[size] | セットの要素。要素は type_idx の昇順で並べる必要があります。
|
annotation_off_item の形式
名前 | 形式 | 説明 |
---|---|---|
annotation_off | uint | ファイルの先頭からアノテーションまでのオフセット。このオフセットは data セクション内の位置までとする必要があります。その位置にあるデータの形式は下記の「annotation_item 」で規定されます。
|
annotation_item
annotation_set_item から参照
data セクションで指定
位置揃え: なし(バイト整列済み)
名前 | 形式 | 説明 |
---|---|---|
visibility | ubyte | このアノテーションの意図された参照可能性(以下を参照)。 |
annotation | encoded_annotation | エンコード済みのアノテーションの内容。上記の「encoded_value エンコード」の「encoded_annotation の形式」で規定されている形式で表します。
|
参照可能性の値
annotation_item
内の visibility
フィールドのオプションは次のとおりです。
名前 | 値 | 説明 |
---|---|---|
VISIBILITY_BUILD | 0x00 | ビルド時(他のコードのコンパイル時など)にのみ参照できることを意図しています |
VISIBILITY_RUNTIME | 0x01 | 実行時に参照できることを意図しています |
VISIBILITY_SYSTEM | 0x02 | ランタイムに参照できますが、基盤となるシステムからのみ参照できる(通常のユーザーコードからは参照できない)ことを意図しています |
encoded_array_item
class_def_item から参照
data セクションで指定
位置揃え: なし(バイト整列済み)
名前 | 形式 | 説明 |
---|---|---|
value | encoded_array | エンコード済みの配列値を表すバイト。上記の「encoded_value エンコード」の「encoded_array の形式」で規定されている形式で表します。
|
hiddenapi_class_data_item
このセクションには、各クラスによって使用される制限付きインターフェースに関するデータが含まれます。
注: Android 10.0 で、非表示 API 機能が導入されました。これは、ブート クラスパス内のクラスの DEX ファイルにのみ適用されます。下記に規定するフラグのリストは、Android の今後のリリースで拡張される可能性があります。詳細については、非 SDK インターフェースの制限をご覧ください。
名前 | 形式 | 説明 |
---|---|---|
size | uint | セクションの合計サイズ。 |
offsets | uint[] | class_idx インデックス付きのオフセットの配列。インデックス class_idx の配列エントリがゼロの場合、この class_idx にデータがないか、すべての非表示 API フラグがゼロであることを意味します。そうでない場合、配列エントリはゼロ以外であり、セクションの先頭からこの class_idx の非表示 API フラグ配列までのオフセットを格納します。
|
flags | uleb128[] | 各クラスの非表示 API フラグを連結した配列。下記の表に、指定可能なフラグの値を示します。フラグはフィールドと同じ順序でエンコードされ、メソッドはクラスデータ内でエンコードされます。 |
制限フラグの種類:
名前 | 値 | 説明 |
---|---|---|
whitelist | 0 | 自由に使用できるインターフェース。公式に文書化されている Android フレームワークのパッケージ インデックスの一部としてサポートされます。 |
greylist | 1 | アプリのターゲット API レベルと無関係に使用できる非 SDK インターフェース。 |
blacklist | 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
アノテーションは、デフォルト バインディングを示す各アノテーション インターフェースに添付されます。
名前 | 形式 | 説明 |
---|---|---|
value | Annotation | このアノテーションのデフォルト バインディング。この型のアノテーションとして表します。アノテーションによって定義されるすべての名前をアノテーションに含める必要はありません。名前がない場合、単にデフォルトがないことを意味します。 |
dalvik.annotation.EnclosingClass
クラスで指定
EnclosingClass
アノテーションは、本来別のクラスのメンバーとして定義されるクラスか、匿名でもメソッド本体内で定義されないクラス(合成内部クラスなど)ごとに添付されます。このアノテーションが添付されたすべてのクラスには、InnerClass
アノテーションも添付されます。また、1 つのクラスに EnclosingClass
アノテーションと EnclosingMethod
アノテーションの両方を添付することはできません。
名前 | 形式 | 説明 |
---|---|---|
value | Class | このクラスに字句スコープが最も近いクラス |
dalvik.annotation.EnclosingMethod
クラスで指定
EnclosingMethod
アノテーションは、メソッド本体の内部で定義される各クラスに添付されます。このアノテーションが添付されたすべてのクラスには、InnerClass
アノテーションも添付されます。また、1 つのクラスに EnclosingClass
アノテーションと EnclosingMethod
アノテーションの両方を添付することはできません。
名前 | 形式 | 説明 |
---|---|---|
value | Method | このクラスに字句スコープが最も近いメソッド |
dalvik.annotation.InnerClass
クラスで指定
InnerClass
アノテーションは、別のクラスの定義の字句スコープ内で定義される各クラスに添付されます。このアノテーションが添付されたクラスには、EnclosingClass
アノテーションまたは EnclosingMethod
アノテーションのどちらかかも添付する必要があります。
名前 | 形式 | 説明 |
---|---|---|
name | String | このクラスに対して最初に宣言されたシンプルな名前(パッケージ プレフィックスは含みません)。このクラスが匿名である場合、名前は null です。
|
accessFlags | int | クラスに対して最初に宣言されたアクセスフラグ(ソース言語とターゲット仮想マシンの間で実行モデルが一致しないために、有効フラグとは異なる場合があります)。 |
dalvik.annotation.MemberClasses
クラスで指定
MemberClasses
アノテーションは、メンバークラスを宣言する各クラスに添付されます(メンバークラスは名前を持つ直接内部クラスです)。
名前 | 形式 | 説明 |
---|---|---|
value | Class[] | メンバークラスの配列 |
dalvik.annotation.MethodParameters
メソッドで指定
注: このアノテーションは Android 7.1 以後に追加されました。それより前の Android リリースでは、存在が無視されます。
MethodParameters
アノテーションは省略可能であり、パラメータ名や修飾子などのパラメータ メタデータを提供するために使用できます。
ランタイムにパラメータ メタデータが不要な場合、メソッドまたはコンストラクタからこのアノテーションを省略してもかまいません。java.lang.reflect.Parameter.isNamePresent()
を使用すると、パラメータにメタデータが存在するかどうかをチェックできます。メタデータが存在しない場合、ランタイムに java.lang.reflect.Parameter.getName()
などの関連リフレクション メソッドが失敗すると、代わりにデフォルトの動作が実行されます。
コンパイラがパラメータ メタデータを含める場合は、enum などの生成クラスの情報を含める必要があります。パラメータ メタデータには、パラメータが合成かどうか、また強制かどうかの情報が含まれるためです。
MethodParameters
アノテーションは個々のメソッド パラメータのみを記述します。したがって、コンパイラは、コードサイズとランタイムの効率を高めるために、パラメータを持たないコンストラクタとメソッドについてはアノテーションを完全に省略できます。
下記で説明する配列は、メソッドに関連付けられた method_id_item
dex 構造体の配列と同じサイズにする必要があります。同じサイズでない場合は、ランタイムに java.lang.reflect.MalformedParametersException
がスローされます。
つまり、method_id_item.proto_idx
-> proto_id_item.parameters_off
-> type_list.size
は、names().length
および accessFlags().length
と同じでなければなりません。
MethodParameters
は、ソースコードで明示的に宣言されていない、または暗黙的に宣言されているものも含むすべてのメソッドの仮パラメータを記述するので、配列のサイズは、ソースコードで宣言された明示的なパラメータのみに基づくシグネチャまたはその他のメタデータ情報と異なる場合があります。また、MethodParameters
には、実際のメソッド シグネチャ内に存在しない型アノテーション レシーバ パラメータに関する情報も含まれていません。
名前 | 形式 | 説明 |
---|---|---|
names | String[] | 関連するメソッドの仮パラメータの名前。配列を null にすることはできませんが、仮パラメータがない場合は空にする必要があります。配列内の値は、そのインデックスを持つ仮パラメータに名前がない場合、null にする必要があります。 パラメータ名の文字列が空の場合、または「.」「;」「[」「/」のいずれかを含む場合、ランタイムに java.lang.reflect.MalformedParametersException がスローされます。
|
accessFlags | int[] | 関連するメソッドの仮パラメータのアクセスフラグ。配列を null にすることはできませんが、仮パラメータがない場合は空にする必要があります。 値は、次の値を持つビットマスクです。
java.lang.reflect.MalformedParametersException がスローされます。
|
dalvik.annotation.Signature
クラス、フィールド、メソッドで指定
Signature
アノテーションは、type_id_item
による表現よりも複雑な型で定義されているクラス、フィールド、またはメソッドごとに添付されます。.dex
形式ではシグネチャの形式を定義しておらず、ソース言語がその言語のセマンティクスを正常に実装するために必要とするシグネチャを表すことのみを意図しています。したがって、通常、シグネチャは仮想マシン実装では解析(または検証)されません。シグネチャの処理は、そのまま上位レベルの API とツール(デバッガなど)に委ねられます。そのため、シグネチャを使用する際は、有効なシグネチャを受け取る場合のみを前提にコードを記述するのではなく、構文上無効なシグネチャに遭遇する場合に備えて明示的な保護手段を講じる必要があります。
シグネチャ文字列は多くの重複する内容を含む傾向があるため、Signature
アノテーションは、重複する要素が必然的に同じ基礎データを参照するような、文字列配列として定義されます。そして、その配列内にあるすべての文字列の連結がシグネチャとされます。シグネチャを別々の文字列に分離する方法に関するルールはありません。その処理は .dex
ファイルを生成するツールに完全に委ねられます。
名前 | 形式 | 説明 |
---|---|---|
value | String[] | このクラスまたはメンバーのシグネチャ。まとめて連結される文字列の配列として表されます。 |
dalvik.annotation.Throws
メソッドで指定
Throws
アノテーションは、1 つ以上の例外タイプをスローするように宣言された各メソッドに添付されます。
名前 | 形式 | 説明 |
---|---|---|
value | Class[] | スローされる例外タイプの配列 |