.dex は、Dalvik バイトコード用のトランスポート形式のファイルです。有効な .dex ファイルであることを保証する構文上の制約と意味論的な制約が存在し、有効な .dex ファイルのみをサポートするランタイムが必要とされます。
一般的な .dex 整合性制約
一般的な整合性制約は、.dex ファイルの大まかな構造に関係します。詳しくは .dex 形式をご覧ください。
| ID | 説明 | 
|---|---|
| G1 | .dexファイルのmagicナンバーは、バージョン 35 ではdex\n035\0でなければなりません。それ以降のバージョンでも同様の形式である必要があります。 | 
| G2 | チェックサムは、ファイル コンテンツ全体の Adler-32 チェックサムでなければなりません( magicフィールドとchecksumフィールドを除く)。 | 
| G3 | 署名は、ファイル コンテンツ全体の SHA-1 ハッシュでなければなりません( magic、checksum、signatureを除く)。 | 
| G4 | 
 
 | 
| G5 | 
 
 | 
| G6 | endian_tagは、ENDIAN_CONSTANTまたはREVERSE_ENDIAN_CONSTANTのいずれかの値を持つ必要があります。 | 
| G7 | 個々の  
             | 
| G8 | ヘッダー内のすべてのオフセット フィールド( map_offを除く)は、4 バイトで揃える必要があります。 | 
| G9 | map_offフィールドは、ゼロであるか、データ セクションを指す必要があります。後者の場合、dataセクションが存在しなければなりません。 | 
| G10 | link、string_ids、type_ids、proto_ids、field_ids、method_ids、class_defs、dataの各セクションは、互いに重複してはならず、また、ヘッダーと重複してはなりません。 | 
| G11 | マップが存在する場合、各マップエントリには有効な型が必要です。それぞれの型は最大 1 回指定できます。 | 
| G12 | マップが存在する場合、各マップエントリにはゼロ以外のオフセットとサイズが必要です。オフセットは、ファイルの対応するセクションを指す必要があります(たとえば、 string_id_itemはstring_idsセクションを指す必要があります)。また、アイテムの明示的または暗黙的なサイズは、セクションの実際の内容およびサイズと一致する必要があります。 | 
| G13 | マップが存在する場合、マップエントリ n+1のオフセットは、マップエントリn plus than size of map entry nのオフセット以上の値でなければなりません。これは、エントリが重複しないことと、エントリの順序が「低いものから高いもの」順であることを暗黙的に意味します。 | 
| G14 | string_id_item、type_id_item、proto_id_item、field_id_item、method_id_item、class_def_item、type_list、code_item、annotations_directory_itemの型のエントリには、4 バイトで揃えたオフセットが必要です。 | 
| G15 | 個々の  個々の  参照される  | 
| G16 | 個々の type_id_itemについて、descriptor_idxフィールドはstring_idsリストへの有効な参照を含む必要があります。参照される文字列は有効な型記述子でなければなりません。 | 
| G17 | 個々の proto_id_itemについて、shorty_idxフィールドはstring_idsリストへの有効な参照を含む必要があります。参照される文字列は有効な短い記述子でなければなりません。また、return_type_idxフィールドはtype_idsセクションに対する有効なインデックスでなければならず、parameters_offフィールドはゼロであるか、dataセクションを指す有効なオフセットでなければなりません。ゼロ以外の場合、パラメータ リストに void エントリを含めることはできません。 | 
| G18 | 個々の field_id_itemについて、class_idxフィールドとtype_idxフィールドはtype_idsリストに対する有効なインデックスでなければなりません。class_idxによって参照されるエントリは配列以外の参照型であることが必要です。さらに、name_idxフィールドはstring_idsセクションへの有効な参照でなければならず、参照されるエントリの内容はMemberName仕様に従う必要があります。 | 
| G19 | 個々の method_id_itemについて、class_idxフィールドはtype_idsセクションへの有効なインデックスでなければならず、参照されるエントリは配列以外の参照型でなければなりません。proto_idフィールドはproto_idsリストへの有効な参照であることが必要です。name_idxフィールドはstring_idsセクションへの有効な参照でなければならず、参照されるエントリの内容はMemberName仕様に従う必要があります。 | 
| G20 | 個々の field_id_itemについて、class_idxフィールドはtype_idsリストに対する有効なインデックスでなければなりません。参照されるエントリは配列以外の参照型であることが必要です。 | 
静的なバイトコード制約
静的な制約は、バイトコードの個々の要素に対する制約です。通常は、制御分析またはデータフロー分析の手法を使用しなくてもチェックできます。
| ID | 説明 | 
|---|---|
| A1 | insns配列を空にすることはできません。 | 
| A2 | insns配列内の最初のオペコードはインデックス 0(ゼロ)を持つ必要があります。 | 
| A3 | insns配列は、有効な Dalvik オペコードのみを含む必要があります。 | 
| A4 | 命令 n+1のインデックスは、可能なオペランドを考慮して、命令nのインデックスに命令nの長さを加えた値でなければなりません。 | 
| A5 | insns配列内の最後の命令は、インデックスinsns_size-1で終了する必要があります。 | 
| A6 | すべての gotoターゲットとif-<kind>ターゲットは、同じメソッド内のオペコードでなければなりません。 | 
| A7 | packed-switch命令のすべてのターゲットは、同じメソッド内のオペコードでなければなりません。ターゲットのサイズとリストは一貫している必要があります。 | 
| A8 | sparse-switch命令のすべてのターゲットは、同じメソッド内のオペコードでなければなりません。対応する表は、一貫性を持ち、「低いものから高いもの」順に並んでいることが必要です。 | 
| A9 | const-string命令とconst-string/jumbo命令のBオペランドは、文字列定数プールに対する有効なインデックスでなければなりません。 | 
| A10 | iget<kind>命令とiput<kind>命令のCオペランドは、フィールド定数プールに対する有効なインデックスでなければなりません。参照されるエントリはインスタンス フィールドを表す必要があります。 | 
| A11 | sget<kind>命令とsput<kind>命令のCオペランドは、フィールド定数プールに対する有効なインデックスでなければなりません。参照されるエントリは静的フィールドを表す必要があります。 | 
| A12 | invoke-virtual命令、invoke-super命令、invoke-direct命令、invoke-static命令のCオペランドは、メソッド定数プールに対する有効なインデックスでなければなりません。 | 
| A13 | invoke-virtual/range命令、invoke-super/range命令、invoke-direct/range命令、invoke-static/range命令のBオペランドは、メソッド定数プールに対する有効なインデックスでなければなりません。 | 
| A14 | 名前が「<」で始まるメソッドは、 .dexファイルに由来するコードではなく、VM によってのみ暗黙的に呼び出される必要があります。唯一の例外は、invoke-directによる呼び出しが可能なインスタンス初期化子です。 | 
| A15 | invoke-interface命令のCオペランドは、メソッド定数プールに対する有効なインデックスでなければなりません。参照されるmethod_idは、(クラスではなく)インターフェースに属している必要があります。 | 
| A16 | invoke-interface/range命令のBオペランドは、メソッド定数プールに対する有効なインデックスでなければなりません。参照されるmethod_idは、(クラスではなく)インターフェースに属している必要があります。 | 
| A17 | const-class命令、check-cast命令、new-instance命令、filled-new-array/range命令のBオペランドは、型定数プールに対する有効なインデックスでなければなりません。 | 
| A18 | instance-of命令、new-array命令、filled-new-array命令のCオペランドは、型定数プールに対する有効なインデックスでなければなりません。 | 
| A19 | new-array命令によって作成される配列のディメンションは、256より小さくなければなりません。 | 
| A20 | new命令で、配列クラス、インターフェース、抽象クラスを参照することはできません。 | 
| A21 | new-array命令によって参照される型は、有効で、かつ非参照型でなければなりません。 | 
| A22 | 命令によってシングル幅の(ペアでない)形式で参照されるすべてのレジスタは、現在のメソッドに対して有効でなければなりません。つまり、レジスタのインデックスが負数でなく、 registers_sizeより小さい値であることが必要です。 | 
| A23 | 命令によってダブル幅(ペア)の形式で参照されるすべてのレジスタは、現在のメソッドに対して有効でなければなりません。つまり、レジスタのインデックスが負数でなく、 registers_size-1より小さい値であることが必要です。 | 
| A24 | invoke-virtual命令とinvoke-direct命令のmethod_idオペランドは、(インターフェースではなく)クラスに属している必要があります。バージョン037より前の Dex ファイルでは、invoke-super命令とinvoke-static命令に同じ制約が適用されます。 | 
| A25 | invoke-virtual/range命令とinvoke-direct/range命令のmethod_idオペランドは、(インターフェースではなく)クラスに属している必要があります。バージョン037より前の Dex ファイルでは、invoke-super/range命令とinvoke-static/range命令に同じ制約が適用されます。 | 
構造的なバイトコード制約
構造的な制約は、バイトコードの複数の要素間の関係に対する制約です。通常は、制御分析またはデータフロー分析の手法を使用しないとチェックできません。
| ID | 説明 | 
|---|---|
| B1 | 引数(レジスタとイミディエイト値)の数と型は、常に命令と一致する必要があります。 | 
| B2 | レジスタペアを切り離すことはできません。 | 
| B3 | レジスタ(またはペア)は、読み取り可能になる前に最初に割り当てる必要があります。 | 
| B4 | invoke-direct命令がインスタンス初期化子またはメソッドを呼び出す場所は、現在のクラスまたはそのスーパークラスの 1 つでなければなりません。 | 
| B5 | インスタンス初期化子は、初期化されていないインスタンスでのみ呼び出される必要があります。 | 
| B6 | インスタンス メソッドは初期化済みのインスタンスでのみ呼び出すことができ、インスタンス フィールドは初期化済みのインスタンスでのみアクセスできます。 | 
| B7 | new-instance命令の結果を保持するレジスタは、同じnew-instance命令がインスタンスの初期化前に再度実行される場合、使用できません。 | 
| B8 | インスタンス初期化子は、インスタンス メンバーがアクセス可能になる前に、別のインスタンス初期化子(同じクラスまたはスーパークラス)を呼び出す必要があります。ただし、継承されないインスタンス フィールドは例外で、別の初期化子と Objectクラス全般を呼び出す前に割り当てることができます。 | 
| B9 | すべての実際のメソッド引数は、それぞれの仮引数との代入互換性を持つ必要があります。 | 
| B10 | 個々のインスタンス メソッド呼び出しについて、実際のインスタンスは、命令で指定されたクラスまたはインターフェースとの代入互換性を持つ必要があります。 | 
| B11 | return<kind>命令は、そのメソッドの戻り値の型と一致する必要があります。 | 
| B12 | スーパークラスの保護されたメンバーにアクセスする場合、アクセスされるインスタンスの実際の型は、現在のクラスまたはそのサブクラスの 1 つでなければなりません。 | 
| B13 | 静的フィールドに格納される値の型は、フィールドの型と代入互換性があるか、フィールドの型に変換可能でなければなりません。 | 
| B14 | フィールドに格納される値の型は、フィールドの型と代入互換性があるか、フィールドの型に変換可能でなければなりません。 | 
| B15 | 配列に格納されるすべての値の型は、配列のコンポーネント型との代入互換性を持つ必要があります。 | 
| B16 | throw命令のAオペランドは、java.lang.Throwableとの代入互換性を持つ必要があります。 | 
| B17 | メソッドの最後のアクセス可能な命令は、後方への gotoまたはブランチ、return、throw命令のいずれかであることが必要です。insns配列を一番下に残すことはできません。 | 
| B18 | 前のレジスタペアの未割り当ての片割れは、他の命令によって再割り当てされるまで読み取りができません(無効と見なされます)。 | 
| B19 | move-result<kind>命令は、(insns配列内で)invoke-<kind>命令の直後に配置する必要があります。ただし、move-result-object命令は唯一の例外で、filled-new-array命令の後に配置することもできます。 | 
| B20 | move-result<kind>命令は、(実際の制御フロー内で)一致するreturn-<kind>命令の直後に配置する必要があります(直接ジャンプすることはできません)。ただし、move-result-object命令は唯一の例外で、filled-new-array命令の後に配置することもできます。 | 
| B21 | move-exception命令は、必ず例外ハンドラ内の最初の命令として配置する必要があります。 | 
| B22 | packed-switch-data、sparse-switch-data、fill-array-dataの各擬似命令は、制御フローからアクセスすることはできません。 |