Use JADX as a Library
Use jadx as a Library
Maven Coordinates
All artifacts are published to Maven Central under the group io.github.skylot.
Search: https://search.maven.org/search?q=jadx
Dependency Setup
Required
1// build.gradle.kts
2dependencies {
3 implementation("io.github.skylot:jadx-core:<version>")
4}
Also add the google() repository — required for the aapt transitive dependency (to be fixed in a future release):
1repositories {
2 google()
3 mavenCentral()
4}
Input Plugins (add one or more)
| Artifact | Purpose |
|---|---|
io.github.skylot:jadx-dex-input | Read .dex files and wrappers (.apk, etc.) |
io.github.skylot:jadx-java-input | Load Java bytecode (.class, .jar) |
io.github.skylot:jadx-java-convert | Java bytecode via dx/d8 conversion — conflicts with jadx-java-input |
io.github.skylot:jadx-smali-input | Smali source input |
io.github.skylot:jadx-raung-input | Raung source input |
Optional: Logging
jadx uses slf4j-api. Add and configure an implementation such as ch.qos.logback:logback-classic.
Core API
Minimal Example — Decompile and Save to Disk
1import java.io.File;
2import jadx.api.JadxArgs;
3import jadx.api.JadxDecompiler;
4
5public class App {
6 public static void main(String[] args) {
7 JadxArgs jadxArgs = new JadxArgs();
8 jadxArgs.setInputFile(new File("classes.dex"));
9 jadxArgs.setOutDir(new File("output"));
10 try (JadxDecompiler jadx = new JadxDecompiler(jadxArgs)) {
11 jadx.load();
12 jadx.save();
13 } catch (Exception e) {
14 e.printStackTrace();
15 }
16 }
17}
Iterating Classes and Methods
Instead of jadx.save(), iterate the decompiled model:
1for (JavaClass cls : jadx.getClasses()) {
2 for (JavaMethod mth : cls.getMethods()) {
3 System.out.println(mth.getName());
4 }
5}
Performance Optimizations
1. Use SimpleCodeWriter (no code attributes needed)
1jadxArgs.setCodeWriterProvider(SimpleCodeWriter::new);
Skips attribute tracking — faster when you only need the raw code text.
2. Disable code cache (single-pass use)
1jadxArgs.setCodeCache(new NoOpCodeCache());
Reduces memory when each class is accessed only once.
Custom Directories (≥ 1.5.1)
By default, temp/cache/config directories are placed in the system temp directory. Override via IJadxFilesGetter:
1jadxArgs.setFilesGetter(new IJadxFilesGetter() {
2 @Override
3 public Path getConfigDir() {
4 return Path.of("config");
5 }
6
7 @Override
8 public Path getCacheDir() {
9 return Path.of("cache");
10 }
11
12 @Override
13 public Path getTempDir() {
14 return Path.of("temp");
15 }
16});
Cache and config are primarily used by plugins; depending on your setup they may not be needed.
Custom Passes
Data available only during decompilation passes can be accessed by registering a custom pass:
1jadx.addCustomPass(myJadxPass);
Alternatively, implement a full jadx plugin.
Android Caveats
jadx is not suited for direct use on Android due to memory and CPU constraints. It may not work on Android API < 26.
- Reference Android app: https://github.com/jadx-decompiler/jadx-lib-android-example
- Fork with Android API 21+ support: https://github.com/developer-krushna/jadx-android-api21
Using the Latest Unstable (Snapshot) Build
Add the Sonatype snapshot repository and use the -SNAPSHOT version:
1// build.gradle.kts
2repositories {
3 maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
4}
5
6dependencies {
7 implementation("io.github.skylot:jadx-core:1.5.2-SNAPSHOT") { isChanging = true }
8 implementation("io.github.skylot:jadx-dex-input:1.5.2-SNAPSHOT") { isChanging = true }
9 implementation("io.github.skylot:jadx-java-input:1.5.2-SNAPSHOT") { isChanging = true }
10 implementation("io.github.skylot:jadx-smali-input:1.5.2-SNAPSHOT") { isChanging = true }
11 implementation("io.github.skylot:jadx-kotlin-metadata:1.5.2-SNAPSHOT") { isChanging = true }
12}
All available snapshot artifacts: https://s01.oss.sonatype.org/content/repositories/snapshots/io/github/skylot/