Skip to content

Use jadx as a library

skylot edited this page Oct 25, 2024 · 11 revisions

From version 1.3.1 jadx artifacts available on maven central repository (list).

Include in project

  1. Add main jadx-core dependency (io.github.skylot:jadx-core).
    Latest release version: Maven Central
    To use the latest unstable build, see Using the latest unstable build
  2. Add google() repository to load aapt dependency (will be fixed in the future)
  3. Add one or several input plugins:
    • jadx-dex-input - allows reading dex files and all wrappers (apk, etc.)
    • jadx-java-input - support java bytecode loading
    • jadx-java-convert - support java bytecode through conversion using dx/d8 tools (conflicts with jadx-java-input)
    • jadx-smali-input - Smali input support
    • jadx-raung-input - Raung input support
  4. (Optional) As soon as jadx uses slf4j-api (manual), you will need to add and configure an implementation library as ch.qos.logback:logback-classic (manual)

Code

Complete example of simple code dump from dex input:

import java.io.File;
import jadx.api.JadxArgs;
import jadx.api.JadxDecompiler;

public class App {
    public static void main(String[] args) {
        JadxArgs jadxArgs = new JadxArgs();
        jadxArgs.setInputFile(new File("classes.dex"));
        jadxArgs.setOutDir(new File("output"));
        try (JadxDecompiler jadx = new JadxDecompiler(jadxArgs)) {
            jadx.load();
            jadx.save();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Instead jadx.save() you can iterate over classes to access necessary info:

for (JavaClass cls : jadx.getClasses()) {
    for (JavaMethod mth : cls.getMethods()) {
        System.out.println(mth.getName());
    }
}

Possible optimizations

  1. If code attributes are not needed, it is possible to switch to a simple code writer:
    jadxArgs.setCodeWriterProvider(SimpleCodeWriter::new);
  2. To reduce memory usage if simple dump is used (class info accessed only once):
    jadxArgs.setCodeCache(new NoOpCodeCache());

Custom directories

In 1.5.1-SNAPSHOT version it is possible to set custom directories for temp, cache and config. Cache and config now used mostly for plugins, so depending on your setup might be not needed.

By default, all directories located in system temp directory. To change that, add code like this:

jadxArgs.setFilesGetter(new IJadxFilesGetter() {
	@Override
	public Path getConfigDir() {
		return Path.of("config");
	}

	@Override
	public Path getCacheDir() {
		return Path.of("cache");
	}

	@Override
	public Path getTempDir() {
		return Path.of("temp");
	}
});

Use on Android

Please note that jadx library is not suited for use on Android, because of limited memory and CPU, also it may not work on Android API < 26.

Example Android app with jadx: https://github.com/jadx-decompiler/jadx-lib-android-example

If Android API 21+ is required, check this fork: https://github.com/developer-krushna/jadx-android-api21

Additional information

Some data available during decompilation only inside jadx passes.

Register your pass using JadxDecompiler.addCustomPass(JadxPass) or create your jadx plugin.

Using the latest unstable build

Add maven snapshot repository and use latest snapshot version (check this directory for all artifacts):

// build.gradle.kts

repositories {
    maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}

dependencies {
    implementation("io.github.skylot:jadx-core:1.5.1-SNAPSHOT") {
        isChanging = true
    }
    implementation("io.github.skylot:jadx-dex-input:1.5.1-SNAPSHOT") {
        isChanging = true
    }
    implementation("io.github.skylot:jadx-java-input:1.5.1-SNAPSHOT") {
        isChanging = true
    }
    implementation("io.github.skylot:jadx-smali-input:1.5.1-SNAPSHOT") {
        isChanging = true
    }
    implementation("io.github.skylot:jadx-kotlin-metadata:1.5.1-SNAPSHOT") {
        isChanging = true
    }
}