Skip to content

How to Decompile JAR Files Using JADX: Extract Full Java Applications

I needed to understand how a third-party library worked internally, but the documentation was incomplete and the source code wasn’t available. All I had was a JAR file. After trying several approaches, I found JADX to be the most reliable tool for decompiling JAR files.

The Problem: No Source Code Access

I was debugging an integration issue with a proprietary library. The error logs weren’t helpful, and I needed to see what the code was actually doing:

error-log.txt
Caused by: java.lang.NullPointerException
at com.example.internal.Processor.transform(Processor.java:42)
at com.example.internal.Handler.process(Handler.java:28)

The stack trace showed line numbers, but without the source code, I was stuck. I needed to decompile the JAR file to understand the logic.

First Attempt: JAR File Inspection

I started by inspecting the JAR file structure:

inspect-jar.sh
jar tf myapp.jar

This gave me a list of files:

jar-contents.txt
META-INF/MANIFEST.MF
com/example/Processor.class
com/example/Handler.class
com/example/utils/StringUtils.class
config/settings.properties

I could see the structure, but the .class files are bytecode, not readable Java source. I needed a decompiler.

Why JADX for JAR Decompilation

I considered several options:

  1. javap: Only disassembles bytecode, doesn’t produce readable source
  2. JD-GUI: Good GUI, but CLI workflow fits better in my pipeline
  3. CFR: Solid decompiler, but JADX handles JAR files more elegantly
  4. JADX: Converts DEX and JAR files to Java source, with both CLI and GUI

JADX stood out because:

  • It extracts the entire JAR structure automatically
  • Preserves package hierarchy in output
  • Handles resources (properties files, XML configs) separately
  • Produces clean, readable Java code

Installing JADX

I installed JADX on macOS using Homebrew:

install-jadx.sh
brew install jadx

On Linux, you can download the release directly:

install-jadx-linux.sh
wget https://github.com/skylot/jadx/releases/download/v1.5.0/jadx-1.5.0.zip
unzip jadx-1.5.0.zip -d jadx
sudo mv jadx/bin/jadx /usr/local/bin/

Verify the installation:

verify-jadx.sh
jadx --version

Decompiling a JAR File

With JADX installed, decompiling a JAR is straightforward:

decompile-jar.sh
jadx myapp.jar

JADX created an output directory with this structure:

output-structure.txt
myapp/
├── sources/
│ └── com/
│ └── example/
│ ├── Processor.java
│ ├── Handler.java
│ └── utils/
│ └── StringUtils.java
└── resources/
├── META-INF/
│ └── MANIFEST.MF
└── config/
└── settings.properties

The sources/ directory contains decompiled Java files, and resources/ contains everything else from the JAR.

Understanding the Output

Let me look at a decompiled class:

Processor.java
package com.example;
import java.util.List;
public class Processor {
private final Config config;
public Processor(Config config) {
this.config = config;
}
public Document transform(List<Document> documents) {
if (documents == null || documents.isEmpty()) {
return null; // Line 42 - the NPE source!
}
// ... processing logic
}
}

Now I could see the null check was missing for individual elements, not the list itself. This explained my error.

Customizing the Output Directory

By default, JADX creates a directory matching the JAR filename. To specify a different output location:

custom-output.sh
jadx myapp.jar -d ./decompiled-sources

Extracting Resources and Manifest

JAR files contain more than just compiled classes. JADX extracts everything:

full-extract.sh
jadx myapp.jar -d ./extracted

After extraction, I could examine the manifest:

MANIFEST.MF
Manifest-Version: 1.0
Main-Class: com.example.Application
Class-Path: lib/dependency1.jar lib/dependency2.jar

And configuration files:

settings.properties
database.url=jdbc:postgresql://localhost:5432/mydb
cache.enabled=true
timeout=30000

This revealed the application’s dependencies and configuration, which helped me understand the runtime requirements.

Using JADX GUI for Interactive Analysis

For deeper exploration, JADX provides a graphical interface:

launch-gui.sh
jadx-gui myapp.jar

The GUI offers:

  • Tree view of all classes and packages
  • Syntax-highlighted code viewer
  • Search functionality across all decompiled code
  • Export options for the entire project

Handling Obfuscated Code

Some JAR files are obfuscated, making decompiled code harder to read:

obfuscated-code.java
public class a {
private String a;
private int b;
public void a(String var1) {
this.a = var1;
}
}

JADX includes deobfuscation options:

deobfuscate.sh
jadx myapp.jar --deobf

This renames classes and methods to more readable names based on usage patterns. While not perfect, it makes the code much easier to navigate.

Batch Processing Multiple JAR Files

When analyzing a project with multiple dependencies:

batch-decompile.sh
for jar in lib/*.jar; do
jadx "$jar" -d "./decompiled/$(basename "$jar" .jar)"
done

This decompiles all JAR files in the lib/ directory, each in its own folder.

CLI Options Worth Knowing

JADX has several useful command-line options:

jadx-options.sh
# Show all available options
jadx --help
# Output only specific packages
jadx myapp.jar --select com.example.api
# Include line numbers in comments
jadx myapp.jar --line-annotate
# Set thread count for faster processing
jadx myapp.jar -j 4

What JADX Cannot Recover

Decompilation has limitations:

  1. Comments: Original comments are lost in compilation
  2. Variable names: Only local variable names from debug info survive
  3. Lambda expressions: May appear as anonymous inner classes
  4. Generic type info: Partial recovery at best
  5. Native methods: JNI code remains opaque

For my debugging session, JADX recovered enough to identify the null check issue. I added proper null handling in my integration code, and the problem was resolved.

When to Use JADX for JAR Decompilation

JADX works well when:

  • You need to debug a library without source code
  • You want to understand an application’s structure
  • You’re analyzing dependencies for security issues
  • You need to extract configuration and resources

For simple class file inspection, javap suffices. For production code analysis, JADX’s comprehensive extraction makes it the better choice.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments