pxb1988/dex2jar · error · DexException
Odex unsupported.
Error message
Odex unsupported.
What it means
DexFileReader validates the 4-byte magic at the start of the container. A 'dey ' magic means an odex (optimized/odexed) file, which dex2jar does not parse; it throws DexException('Odex unsupported.'). An odex contains a DVM-specific pre-optimized format rather than a portable DEX.
Solutions
- Obtain the portable classes.dex instead — extract from the APK, or deopt/deodex the odex (e.g. with an oat/dex deoptimizer tool matching the device's Android version)
- Check the file magic before parsing: read the first 4 bytes and only pass 'dex\n' files to DexFileReader
- Catch DexException around DexFileReader open/accept to classify the input cleanly
Example fix
// before
new DexFileReader(odexFile);
// after
byte[] magic = readFirstBytes(odexFile, 4);
if (!Arrays.equals(magic, new byte[]{'d','e','y','\n'})) {
new DexFileReader(odexFile); // proceed only for real dex
} else {
throw new IllegalArgumentException("deodex the file first: " + odexFile);
} Defensive patterns
Strategy: validation
Validate before calling
static boolean isPortableDex(Path p) throws IOException {
byte[] m = new byte[4];
try (InputStream in = Files.newInputStream(p)) {
if (in.read(m) != 4) return false;
}
return m[0]=='d' && m[1]=='e' && m[2]=='x' && m[3]=='\n';
} Try / catch
try {
DexFileReader reader = new DexFileReader(file);
} catch (DexException e) {
if (e.getMessage().contains("Odex")) {
throw new IllegalStateException("deodex required: " + file, e);
}
throw e;
} Prevention
- Never feed .odex or extracted system files directly to DexFileReader — deodex first
- Check the 'dex\n' / 'dey\n' magic before opening any container
- Extract classes.dex from the APK when available instead of device-optimized artifacts
When it happens
Trigger: Opening an .odex file (or any stream whose first bytes are 'dey\n') with DexFileReader or higher-level APIs that delegate to it.
Common situations: Trying to decompile system-app odex files pulled from a device /system partition; passing a yanked odex instead of its corresponding dex; old baksmali-style workflows.
Related errors
- Magic unsupported.
- Endian_tag unsupported
- The source file is not a .dex or .zip file
- the src file not a .dex or zip file
- Encountered RESTART_LOCAL on new v
AI-assisted analysis of pxb1988/dex2jar@b5bda4fb49 (2026-09-08).
Data as JSON: /api/errors/525aa16dcfdb3de7.
Report an issue: GitHub.
Appendix: source
Thrown at dex-reader/src/main/java/com/googlecode/d2j/reader/DexFileReader.java:162
final int dex_version;
/**
* read dex from a {@link ByteBuffer}.
*
* @param in
*/
public DexFileReader(ByteBuffer in) {
in.position(0);
in = in.asReadOnlyBuffer().order(ByteOrder.BIG_ENDIAN);
int magic = in.getInt() & 0xFFFFFF00;
final int MAGIC_DEX = 0x6465780A & 0xFFFFFF00;// hex for 'dex ', ignore the 0A
final int MAGIC_ODEX = 0x6465790A & 0xFFFFFF00;// hex for 'dey ', ignore the 0A
if (magic == MAGIC_DEX) {
// ok
} else if (magic == MAGIC_ODEX) {
throw new DexException("Odex unsupported.");
} else {
throw new DexException("Magic unsupported.");
}
int version = in.getInt() >> 8;
if (version < DEX_035 || version > DEX_040) {
System.err.println("Unknown DEX version. Trying anyway...");
}
this.dex_version = version;
in.order(ByteOrder.LITTLE_ENDIAN);
// skip uint checksum
// and 20 bytes signature
// and uint file_size
// and uint header_size 0x70
skip(in, 4 + 20 + 4 + 4);
int endian_tag = in.getInt();
if (endian_tag != ENDIAN_CONSTANT) {
View on GitHub (pinned to b5bda4fb49)