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:
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:
jar tf myapp.jarThis gave me a list of files:
META-INF/MANIFEST.MFcom/example/Processor.classcom/example/Handler.classcom/example/utils/StringUtils.classconfig/settings.propertiesI 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:
- javap: Only disassembles bytecode, doesn’t produce readable source
- JD-GUI: Good GUI, but CLI workflow fits better in my pipeline
- CFR: Solid decompiler, but JADX handles JAR files more elegantly
- 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:
brew install jadxOn Linux, you can download the release directly:
wget https://github.com/skylot/jadx/releases/download/v1.5.0/jadx-1.5.0.zipunzip jadx-1.5.0.zip -d jadxsudo mv jadx/bin/jadx /usr/local/bin/Verify the installation:
jadx --versionDecompiling a JAR File
With JADX installed, decompiling a JAR is straightforward:
jadx myapp.jarJADX created an output directory with this structure:
myapp/├── sources/│ └── com/│ └── example/│ ├── Processor.java│ ├── Handler.java│ └── utils/│ └── StringUtils.java└── resources/ ├── META-INF/ │ └── MANIFEST.MF └── config/ └── settings.propertiesThe sources/ directory contains decompiled Java files, and resources/ contains everything else from the JAR.
Understanding the Output
Let me look at a decompiled class:
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:
jadx myapp.jar -d ./decompiled-sourcesExtracting Resources and Manifest
JAR files contain more than just compiled classes. JADX extracts everything:
jadx myapp.jar -d ./extractedAfter extraction, I could examine the manifest:
Manifest-Version: 1.0Main-Class: com.example.ApplicationClass-Path: lib/dependency1.jar lib/dependency2.jarAnd configuration files:
database.url=jdbc:postgresql://localhost:5432/mydbcache.enabled=truetimeout=30000This 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:
jadx-gui myapp.jarThe 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:
public class a { private String a; private int b;
public void a(String var1) { this.a = var1; }}JADX includes deobfuscation options:
jadx myapp.jar --deobfThis 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:
for jar in lib/*.jar; do jadx "$jar" -d "./decompiled/$(basename "$jar" .jar)"doneThis decompiles all JAR files in the lib/ directory, each in its own folder.
CLI Options Worth Knowing
JADX has several useful command-line options:
# Show all available optionsjadx --help
# Output only specific packagesjadx myapp.jar --select com.example.api
# Include line numbers in commentsjadx myapp.jar --line-annotate
# Set thread count for faster processingjadx myapp.jar -j 4What JADX Cannot Recover
Decompilation has limitations:
- Comments: Original comments are lost in compilation
- Variable names: Only local variable names from debug info survive
- Lambda expressions: May appear as anonymous inner classes
- Generic type info: Partial recovery at best
- 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