MuntashirAkon/AppManager · error · IOException
ODEX isn't supported.
Error message
ODEX isn't supported.
What it means
This DexClasses constructor builds a class-name map from a dex/odex file via dexlib2. ODEX files use optimized opcodes whose semantics differ from standard dex; the code rejects them before disassembly unless an Odex-specific resolver is configured — but supportsOptimizedOpcodes() on the main dex triggers an explicit IOException('ODEX isn't supported.') because the rest of the pipeline (smali/baksmali handling here) expects plain dex. It exists to fail fast instead of producing wrong decompiled output.
Source
Thrown at app/src/main/java/io/github/muntashirakon/AppManager/dex/DexClasses.java:78
DexBackedDexFile dexFile = dexEntry.getDexFile();
// Store list of classes
for (ClassDef classDef : dexFile.getClasses()) {
String name = formatter.getType(classDef.getType());
if (name.endsWith(";")) name = name.substring(0, name.length() - 1);
if (name.startsWith("L")) {
name = name.substring(1).replace('/', '.');
}
mClassNameClassDefMap.put(name, classDef);
String baseClass = DexUtils.getClassNameWithoutInnerClasses(name);
List<String> classes = mBaseClassNestedClassMap.get(baseClass);
if (classes == null) {
classes = new ArrayList<>();
mBaseClassNestedClassMap.put(baseClass, classes);
}
classes.add(name);
}
if (dexFile.supportsOptimizedOpcodes()) {
throw new IOException("ODEX isn't supported.");
}
if (dexFile instanceof DexBackedOdexFile) {
mOptions.inlineResolver = InlineMethodResolver.createInlineMethodResolver(
((DexBackedOdexFile) dexFile).getOdexVersion());
}
}
}
public DexClasses(@NonNull InputStream inputStream, @IntRange(from = -1) int apiLevel) throws IOException {
mOpcodes = apiLevel < 0 ? Opcodes.getDefault() : Opcodes.forApi(apiLevel);
mOptions = new BaksmaliOptions();
// options
mOptions.deodex = false;
mOptions.implicitReferences = false;
mOptions.parameterRegisters = true;
mOptions.localsDirective = true;
mOptions.sequentialLabels = true;
mOptions.debugInfo = BuildConfig.DEBUG;View on GitHub (pinned to 0152f468fc)
Solutions
- Supply the original classes.dex from the APK instead of the device-compiled odex
- Deoptimize first: pull the APK from the server, or use a tool that converts odex to dex (e.g. baksmali's odex support / vdex-odex extractors)
- If you truly need odex handling, use a code path that sets up DexBackedOdexFile with InlineMethodResolver instead of this constructor
- Skip odex-only entries when iterating app artifacts and log them as unsupported
Example fix
// before
new DexClasses(odexPath, options); // IOException: ODEX isn't supported
// after
File apk = new File("/data/app/com.example/base.apk");
if (hasPlainDex(apk)) {
new DexClasses(apk, options);
} else {
throw new UnsupportedOperationException("App is odex-only; deoptimize or pull APK from server");
} Defensive patterns
Strategy: validation
Validate before calling
DexBackedDexFile dexFile = DexBackedDexFile.fromInputStream(options, new BufferedInputStream(in));
boolean isOdex = dexFile.supportsOptimizedOpcodes();
if (isOdex) throw new UnsupportedOperationException("Supply a plain classes.dex, not an odex"); Type guard
boolean isPlainDex(DexBackedDexFile f) { return !f.supportsOptimizedOpcodes(); } Try / catch
try {
new DexClasses(path, options);
} catch (IOException e) {
if (String.valueOf(e.getMessage()).contains("ODEX")) {
Log.w(TAG, "odex not supported; pull the APK from server or deoptimize first");
}
} Prevention
- Always analyze the original APK's classes.dex, not on-device odex artifacts
- Detect odex files by magic ('dey') before loading
- Skip or convert odex entries in batch decompilation jobs
When it happens
Trigger: Constructing DexClasses over a DexFile whose supportsOptimizedOpcodes() returns true — i.e. an odex file (or a dex that claims optimized opcodes) was supplied where a plain classes.dex was expected: pointing the loader at an odex (e.g. system app's .odex, framework .art/odex extract), or loading an extracted dex that was pre-optimized.
Common situations: Trying to decompile a system app whose code is compiled as odex on-device (no classes.dex present); analyzing a vendor ROM with heavy ART pre-optimization; passing the wrong file from an APK's extracted artifacts.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- {className} could not be found.
- {parserErrors} syntax errors during parsing and/or lexing.
- {syntaxErrors} syntax errors during dex creation
- Could not generate class from smali.
- InputStream is not a dex, odex file.
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/cba47aa557a9362d.
Report an issue: GitHub.