.dex 파일은 Dalvik 바이트 코드의 전송 포맷입니다. 파일이 유효한 .dex 파일이 되기 위한 특정한 문법적 제약 조건과 의미적 제약 조건이 있으며, 유효한 .dex 파일만 지원하기 위한 런타임이 필요합니다.
일반 .dex 무결성 제약 조건
일반 무결성 제약 조건은 .dex 형식에 자세히 설명된 것처럼 .dex 파일의 대규모 구조와 관련이 있습니다.
| 식별자 | 설명 | 
|---|---|
| G1 | .dex파일의magic숫자는dex\n035\0또는dex\n037\0이어야 합니다. | 
| G2 | 체크섬은 magic및checksum필드를 제외한 전체 파일 콘텐츠의 Adler-32 체크섬이어야 합니다. | 
| G3 | 서명은 magic,checksum,signature를 제외한 전체 파일 콘텐츠의 SHA-1 해시여야 합니다. | 
| G4 | file_size는 바이트 단위의 실제 파일 크기와 일치해야 합니다. | 
| G5 | header_size는 값이0x70이어야 합니다. | 
| G6 | endian_tag는 값이ENDIAN_CONSTANT또는REVERSE_ENDIAN_CONSTANT중 하나여야 합니다. | 
| G7 | 각 link,string_ids,type_ids,proto_ids,field_ids,method_ids,class_defs,data섹션에서offset및size필드는 모두 0이거나 모두 0이 아니어야 합니다. 후자의 경우 오프셋은 4바이트로 정렬되어야 합니다. | 
| G8 | 헤더에서 map_off를 제외한 모든 오프셋 필드는 4바이트로 정렬되어야 합니다. | 
| G9 | map_off필드는 0이거나 데이터 섹션을 가리켜야 합니다. 후자의 경우에는data섹션이 있어야 합니다. | 
| G10 | link,string_ids,type_ids,proto_ids,field_ids,method_ids,class_defs,data섹션 중 어느 섹션도 서로 겹치거나 헤더와 겹쳐서는 안 됩니다. | 
| G11 | 지도가 있는 경우 각 지도 항목의 유형은 유효해야 합니다. 각 유형은 최대 한 번만 표시될 수 있습니다. | 
| G12 | 지도가 있는 경우 각 지도 항목의 오프셋과 크기는 0이 아니어야 합니다. 오프셋은 파일의 관련 섹션을 가리켜야 하고(예: 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 | 각 string_id_item의string_data_off필드에는data섹션의 유효한 참조가 포함되어야 합니다. 참조된string_data_item의 경우data필드에는 유효한 MUTF-8 문자열이 포함되어야 하고utf16_size는 문자열의 디코딩된 길이와 일치해야 합니다. | 
| G16 | type_id_item마다descriptor_idx필드에는string_ids목록의 유효한 참조가 포함되어야 합니다. 참조된 문자열은 유효한 유형 설명어여야 합니다. | 
| G17 | proto_id_item마다shorty_idx필드에는string_ids목록의 유효한 참조가 포함되어야 합니다. 참조된 문자열은 유효한 짧은 설명어여야 합니다. 또한,return_type_idx필드는type_ids섹션의 유효한 색인이어야 하고,parameters_off필드는 0이거나data섹션을 가리키는 유효한 오프셋이어야 합니다. 0이 아닌 경우 매개변수 목록에는 무효한 항목이 있어서는 안 됩니다. | 
| 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목록의 유효한 색인이어야 합니다. 참조된 항목은 비배열 참조 유형이어야 합니다. | 
정적 바이트 코드 제약 조건
정적 제약 조건은 바이트 코드의 개별 요소에 적용되는 제약 조건입니다. 일반적으로 정적 제약 조건은 제어 흐름 또는 데이터 흐름 분석 기법을 사용하지 않고 확인할 수 있습니다.
| 식별자 | 설명 | 
|---|---|
| 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명령어도 마찬가지여야 합니다. | 
구조적 바이트 코드 제약 조건
구조적 제약 조건은 바이트 코드의 여러 요소 간의 관계에 적용되는 제약 조건입니다. 일반적으로 구조적 제약 조건은 제어 흐름 또는 데이터 흐름 분석 기법을 사용하지 않고는 확인할 수 없습니다.
| 식별자 | 설명 | 
|---|---|
| B1 | 인수의 개수와 유형(레지스터 및 즉시 값)은 항상 명령어와 일치해야 합니다. | 
| B2 | 레지스터 쌍은 분리해서는 안 됩니다. | 
| B3 | 레지스터(또는 쌍)를 읽으려면 먼저 할당해야 합니다. | 
| B4 | invoke-direct명령어는 현재 클래스 또는 하나의 슈퍼클래스에서만 인스턴스 이니셜라이저 또는 메서드를 호출해야 합니다. | 
| B5 | 인스턴스 이니셜라이저는 초기화되지 않은 인스턴스에서만 호출되어야 합니다. | 
| B6 | 인스턴스 메서드는 이미 초기화된 인스턴스에서만 호출할 수 있고, 이미 초기화된 인스턴스에서만 인스턴스 필드에 액세스할 수 있습니다. | 
| B7 | 인스턴스가 초기화되기 전에 new-instance명령어가 다시 실행되는 경우 같은new-instance명령어의 결과가 있는 레지스터를 사용해서는 안 됩니다. | 
| B8 | 인스턴스 멤버에 액세스하려면 먼저 인스턴스 이니셜라이저가 다른 인스턴스 이니셜라이저(동일한 클래스 또는 슈퍼클래스)를 호출해야 합니다.
           예외는 일반적으로 다른 이니셜라이저를 호출하기 전에 할당될 수 있는 상속되지 않은 인스턴스 필드와 Object클래스입니다. | 
| B9 | 모든 실제 메서드 인수는 각 형식 인수와 대입 호환이 가능해야 합니다. | 
| B10 | 각 인스턴스 메서드 호출에서 실제 인스턴스는 명령어에 지정된 클래스 또는 인터페이스와 대입 호환이 가능해야 합니다. | 
| B11 | return<kind>명령어는 메서드의 반환 유형과 일치해야 합니다. | 
| B12 | 슈퍼클래스의 보호된 멤버에 액세스할 경우 액세스되는 인스턴스의 실제 유형은 현재 클래스이거나 서브클래스 중 하나여야 합니다. | 
| B13 | 정적 필드에 저장되는 값 유형은 필드 유형과 대입 호환이 가능하거나 그 필드 유형으로 변환 가능해야 합니다. | 
| B14 | 필드에 저장되는 값 유형은 필드 유형과 대입 호환이 가능하거나 그 필드 유형으로 변환 가능해야 합니다. | 
| B15 | 배열에 저장되는 모든 값의 유형은 배열의 구성요소 유형과 대입 호환이 가능해야 합니다. | 
| B16 | throw명령어의A피연산자는java.lang.Throwable과 대입 호환이 가능해야 합니다. | 
| B17 | 마지막으로 도달할 수 있는 메서드 명령어는 역방향 goto또는 분기이거나return또는throw명령어이어야 합니다.insns배열을 하단에 둘 수 없어야 합니다. | 
| B18 | 이전 레지스터 쌍 중 할당되지 않은 절반은 다른 명령어에 의해 다시 할당될 때까지 읽을 수 없습니다(유효하지 않은 것으로 간주됨). | 
| B19 | insns배열에서move-result<kind>명령어 바로 앞에는invoke-<kind>명령어가 와야 합니다. 단,move-result-object명령어는 예외입니다. 이 명령어 앞에는filled-new-array명령어가 올 수도 있습니다. | 
| B20 | 실제 제어 흐름에서 move-result<kind>명령어 바로 앞에는 일치하는return-<kind>명령어가 와야 합니다(바로 건너뛸 수 없어야 함). 단,move-result-object명령어는 예외입니다. 이 명령어 앞에는filled-new-array명령어가 올 수도 있습니다. | 
| B12 | move-exception명령어는 예외 핸들러의 첫 번째 명령어로만 표시되어야 합니다. | 
| B22 | packed-switch-data,sparse-switch-data및fill-array-data의사 명령어는 제어 흐름을 통해 도달 가능해서는 안 됩니다. |