Decompiling DEX to Java Source Code: A Detailed Guide
DEX (Dalvik Executable) files are Android’s compiled bytecode format. To convert them back to readable Java source code, follow this comprehensive process:
1. Key Tools Required
Tool | Purpose |
---|---|
dex2jar | Converts DEX to Java-compatible JAR |
Java Decompiler | Converts JAR to Java source |
APK Tool | Extracts DEX from APK (optional) |
JADX | All-in-one decompiler (recommended) |
2. Step-by-Step Process
Option 1: Using dex2jar + Java Decompiler
- Extract DEX from APK:
unzip app.apk -d apk_out
# DEX files: classes.dex, classes2.dex, etc.
- Convert DEX to JAR:
d2j-dex2jar.sh apk_out/classes.dex -o classes.jar
- Decompile JAR to Java:
- Use JD-GUI (GUI tool): Open
classes.jar
- Or CFR (CLI):
bash java -jar cfr.jar classes.jar --outputdir src/
Option 2: Using JADX (Recommended)
- Decompile directly:
jadx -d src app.apk # For APK
jadx -d src classes.dex # For DEX file
- Key JADX flags:
jadx --show-version --deobfuscate -r -d src app.apk
--deobfuscate
: Rename obfuscated classes/vars-r
: Skip resources (faster decompilation)
3. Example Workflow
Input: app.apk
with obfuscated code
Goal: Decompile to readable Java
- Use JADX:
jadx --deobfuscation-on --output-dir src app.apk
- Output Structure:
src/
├── com/
│ └── example/
│ ├── MainActivity.java
│ └── utils/
│ └── NetworkHelper.java
├── resources/
└── AndroidManifest.xml
- Decompiled Java Sample:
// Before deobfuscation
public class a extends Activity {
protected void onCreate(Bundle b) {
super.onCreate(b);
setContentView(0x7f0b001c); // R.layout.activity_main
}
}
// After deobfuscation (JADX output)
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
4. Handling Common Issues
- Multi-DEX APKs:
JADX automatically processes allclasses*.dex
files. - Obfuscated Code:
- Use JADX’s
--deobfuscation-on
- Enable renaming in dex2jar:
d2j-dex2jar.sh --keep-bridge-syn ...
- Incomplete Decompilation:
- Switch tools: Try FernFlower or CFR for problematic files
java -jar fernflower.jar classes.jar src/
5. Advanced Scenarios
Decompiling System DEX (e.g., framework.jar):
- Pull from device:
adb pull /system/framework/framework.jar
- Extract DEX:
unzip framework.jar classes.dex
- Decompile with JADX:
jadx classes.dex -d framework_src
Dynamic Analysis:
- Use Frida to dump runtime DEX:
Java.perform(() => {
const dex = Java.openClassFile('/data/local/tmp/dump.dex').load();
});
6. Legal & Ethical Considerations
- Legal Compliance: Decompile only apps you own or have explicit permission for.
- Obfuscation Best Practices:
# ProGuard rules to prevent decompilation
-keep class com.example.** { *; }
-useuniqueclassmembernames
7. Comparison of Java Decompilers
Tool | Speed | Readability | Obfuscation Handling |
---|---|---|---|
JADX | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
CFR | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
FernFlower | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
JD-GUI | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
Final Recommendations
- Use JADX for 90% of cases (CLI + GUI versions available)
- Combine with dex2jar for edge-case files
- Enable deobfuscation for production apps
- Verify decompiled code against smali (assembly-like) when debugging
Note: Perfect decompilation isn’t always possible due to compiler optimizations. Expect to see some synthetic classes or goto statements in complex code.