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)

ArtifactPurpose
io.github.skylot:jadx-dex-inputRead .dex files and wrappers (.apk, etc.)
io.github.skylot:jadx-java-inputLoad Java bytecode (.class, .jar)
io.github.skylot:jadx-java-convertJava bytecode via dx/d8 conversion — conflicts with jadx-java-input
io.github.skylot:jadx-smali-inputSmali source input
io.github.skylot:jadx-raung-inputRaung 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.


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/