Android DEX file format
Dalvik Executable format — compiled bytecode for the Android runtime.
- MIME type
- application/octet-stream
- Extensions
- .dex
- Category
- Executables & bytecode
Magic-number signature
| 0x00000000 | 6465780A | dex· | 'dex' + newline |
About the Android DEX format
A DEX file is every compiled class of an Android app merged into one file, which is the whole point of the format: instead of thousands of small class files each repeating the names of the types they touch, a DEX has one shared set of tables — strings, types, prototypes, fields, methods — and every class definition refers into them by index. The header is a fixed 112 bytes of sizes and offsets pointing at those tables, so a reader can jump straight to whichever one it needs, and the bytecode itself is register-based rather than stack-based, which is why DEX instructions do not resemble JVM ones at all.
Header layout, byte by byte
| Offset | Length | Field | Meaning |
|---|---|---|---|
| 0 | 8 | magic (DEX_FILE_MAGIC) | The bytes 64 65 78 0A, then three ASCII digits, then a NUL — 'dex\n039\0' for example. The version digits matter: 035 predates Android 7, 037 arrived with Android 7 and default methods, 038 with Android 8, 039 with Android 9, 040 with Android 10. A device refuses a DEX whose version is newer than it knows. |
| 8 | 4 | checksum | Adler-32 of the whole file after this field. It is the first thing the runtime verifies, so any edit anywhere in a DEX must end with this value being recomputed — which is exactly why hand-patching one byte produces a file that will not install. |
| 12 | 20 | signature | SHA-1 of everything after it. Not a security signature — it is a content identifier used by the runtime and by build caches to notice that two DEX files are the same, and it also has to be recomputed after any modification. |
| 32 | 4 | file_size | The complete size of the DEX in bytes. Comparing it with the actual file length is the cheapest truncation test there is, and it is what catches a classes.dex extracted from a damaged APK. |
| 36 | 4 | header_size | The header's own length, fixed at 0x70 (112). Every table offset below is measured from the start of the file, and the data proper begins after this header, so a value other than 0x70 means the file is not a DEX a stock runtime will accept. |
| 40 | 4 | endian_tag | 0x12345678 written in the file's own byte order. A file storing 0x78563412 is big-endian, which is legal in the specification and effectively never seen; its practical use is proving that a parser has the byte order right before it reads any offsets. |
| 44 | 8 | link_size + link_off | Two four-byte fields for statically linked data. Unused by every normal toolchain, so both read zero, and a nonzero pair is a strong hint the file came from something other than d8 or dx. |
| 52 | 4 | map_off | Offset of the map_list, a table of every section in the file with its type code, count and offset. It is the closest thing a DEX has to a table of contents, and it is where a tool looks for sections the header itself does not name, such as call sites and method handles. |
| 56 | 8 | string_ids_size + string_ids_off | Count and offset of the string identifier table — every class name, method name, field name and literal in the app, stored in modified UTF-8. This table is the single most useful thing in a DEX for triage, because reading it tells you what the app touches without disassembling a line. |
| 64 | 24 | type_ids, proto_ids, field_ids | Three more count-and-offset pairs at 64, 72 and 80, indexing type descriptors, method prototypes and field references. Each is a pair of four-byte values in the same size-then-offset order, and the id tables have hard ceilings — the 65536-method limit that forces multidex comes from the index width these tables use. |
| 88 | 16 | method_ids + class_defs | Count and offset of the method reference table at 88, and of the class definition table at 96. The class_defs table is the entry point for anything that lists an app's classes: each entry names the type, its superclass, its interfaces, its source file and where its data lives. |
| 104 | 8 | data_size + data_off | Size and offset of the data section, which holds everything variable-length: code items, string bytes, annotations, encoded arrays. It runs to the end of the header-described file, and the id tables above are effectively an index into it. |
Telling it apart from its neighbours
| Easily confused with | How to tell |
|---|---|
| Java class file | Both are compiled Java, and DEX is built from class files, but they share no bytes. A class file starts CA FE BA BE and holds exactly one type with a stack-based instruction set; a DEX starts 'dex' plus a newline and holds every type in the app with a register-based one. An APK contains DEX and no .class entries at all. |
| Android APK | The relationship people get wrong: a DEX is not an archive and an APK is not bytecode. The APK is the ZIP; classes.dex, classes2.dex and so on are entries inside it. If offset 0 reads 50 4B 03 04 you are holding the package, and the DEX magic will appear further in, at the start of each entry's decompressed data. |
| odex/vdex/oat | The ahead-of-time compiled artefacts on a device are separate formats with their own magic, not DEX files with extra fields, even though tools loosely call them 'optimised dex'. Pulling one off a device and expecting a DEX parser to read it does not work; what a parser wants is the classes.dex from inside the APK. |
| Multidex classes2.dex | Not a different format — identical header, identical version — just a second file in the same APK because the method id table cannot exceed 65536 entries. Tools that report only the first file's classes are reading classes.dex and stopping; the others are named classes2.dex, classes3.dex and upward with no zero-padding. |
How these files break
- A stale checksum or signature after editing. Change one byte of bytecode and the Adler-32 at offset 8 and the SHA-1 at offset 12 no longer describe the file, so the runtime rejects it at install time. Every legitimate DEX-rewriting tool recomputes both, which is why editing a DEX by hand almost never works.
- Truncation. file_size at offset 32 states how long the file should be, so a DEX cut short by a failed extraction is detectable in four bytes without parsing anything. The symptom otherwise is a table offset that points past the end of the file.
- Table offsets that no longer match after an insertion. Every table is located by an absolute offset from the start of the file, so inserting or removing a string shifts everything after it, and a header that was not fully rewritten sends the parser into the middle of another table. It reads a plausible count and then fails on nonsense.
- A version the device is too old for. Not damage, but it presents as a corrupt file: an APK built with a DEX version above what the runtime supports fails to install with a message about the file being invalid rather than about the version, and the three ASCII digits at offset 4 are where the real answer is.
Where the format stands today
DEX is what Android actually runs. Every APK contains at least one classes.dex, produced by d8 from the class files that javac or the Kotlin compiler emitted, and ART either interprets it or compiles it ahead of time on the device. It has no life outside Android — nothing else consumes it, and no other platform has adopted it — but within Android it is unavoidable: shrinking, obfuscation and the 65536-method limit that forces multidex are all consequences of this format's tables. For analysis it is a gift compared with a stripped native binary, because the string and type tables spell out class names, method names and literals in the clear even in an obfuscated app, which is why an APK can be understood so much faster than an equivalent ELF.
Open Android DEX files on this site
Every one of these runs in your browser — the file never leaves your machine.
Related formats
Formats that are easy to confuse with Android DEX — compare their leading bytes.
| Format | First bytes | Extension |
|---|---|---|
| Android APK | 50 4B 03 04 | .apk |
| Java class file | CA FE BA BE | .class |
| ELF executable | 7F 45 4C 46 | .elf |