
Bindings Python pour JADX.
Bindings Python pour JADX via JPype. Décompilateur de fichiers APK et DEX Android en code source Java depuis Python.
from pyjadx import Jadx
with Jadx("app.apk") as jadx:
for cls in jadx.classes:
print(cls.full_name)
print(cls.code)
JADX est le principal décompilateur Android open-source — il produit un code source Java/Kotlin propre à partir du bytecode Dalvik, en préservant les hiérarchies de classes, les génériques, la gestion des exceptions et les annotations. pyjadx intègre cela dans Python sans surcharge de sous-processus : JADX s'exécute directement dans le processus via JPype.
pip install pyjadx
Prérequis : JDK 11+ (les JAR de JADX sont téléchargés automatiquement lors de la première utilisation).
from pyjadx import Jadx
with Jadx("app.apk") as jadx:
# All top-level classes (inner classes via cls.inner_classes)
for cls in jadx.classes:
print(cls.full_name, len(cls.methods), "methods")
# Search by fully qualified name
main = jadx.search_class("com.example.MainActivity")
if main:
print(main.code)
# Method-level decompilation
for method in main.methods:
print(f"{method.name}: {method.code}")
# Cross-references
for method in main.methods:
print(f"{method.name} called by: {[c.name for c in method.callers]}")
# Package navigation
for pkg in jadx.packages:
print(pkg.name, len(pkg.classes), "classes")
| Format | Exemple |
|---|---|
| APK | Jadx("app.apk") |
| DEX | Jadx("classes.dex") |
| Multi-DEX APK | Géré de manière transparente — toutes les classes fusionnées |
Jadx(path, *, threads=None, mode="auto", code_cache=False)Point d'entrée principal. Utilisez-le comme gestionnaire de contexte ou appelez load()/close() manuellement.
| Paramètre | Description |
|---|---|
path | Chemin vers le fichier APK ou DEX |
threads | Taille du pool de threads JADX (None = nombre de CPU) |
mode | "auto", "restructure", "simple" ou "fallback" |
code_cache | False = cache en mémoire (par défaut), True = cache sur disque |
Propriétés :
| Propriété | Type | Description |
|---|---|---|
classes | list[JavaClass] | Classes de premier niveau de tous les fichiers DEX |
packages | list[JavaPackage] | Navigation au niveau des paquets |
class_count | int | Nombre de classes de premier niveau |
java | JObject | Passerelle vers l'objet jadx.api.JadxDecompiler sous-jacent |
Méthodes :
| Méthode | Description |
|---|---|
load() | Charge et résout les classes (appelé par __enter__) |
close() | Libère les ressources (appelé par __exit__) |
decompile_all() | Décompile toutes les classes immédiatement |
search_class(name) | Trouve une classe par son nom qualifié complet |
JavaClass| Propriété | Type | Description |
|---|---|---|
name | str | Nom court ("MainActivity") |
full_name | str | Nom qualifié complet ("com.example.MainActivity") |
package | str | Nom du paquet |
code | str | Code source Java décompilé (paresseux, mis en cache) |
smali | str | Désassemblage Smali (paresseux, mis en cache) |
methods | list[JavaMethod] | Méthodes de cette classe |
fields | list[JavaField] | Champs de cette classe |
inner_classes | list[JavaClass] | Classes internes/anonymes |
declaring_class | JavaClass | None | Classe parente (si interne) |
top_class | JavaClass | Classe englobante la plus externe |
dependencies | list[JavaClass] | Classes dont cette classe dépend |
is_inner | bool | Indique s'il s'agit d'une classe interne |
java | JObject | Passerelle vers jadx.api.JavaClass |
JavaMethod| Propriété | Type | Description |
|---|---|---|
name | str | Nom de la méthode |
full_name | str | Nom qualifié complet avec la classe |
code | str | Code source décompilé (paresseux, mis en cache) |
callers | list[JavaMethod] | Méthodes qui appellent celle-ci (paresseux, mis en cache) |
callees | list[JavaMethod] | Méthodes que celle-ci appelle (paresseux, mis en cache) |
override_related | list[JavaMethod] | Chaîne de redéfinition bidirectionnelle |
declaring_class | JavaClass | Classe à laquelle cette méthode appartient |
java | JObject | Passerelle vers jadx.api.JavaMethod |
JavaField| Propriété | Type | Description |
|---|---|---|
name | str | Nom du champ |
full_name | str | Nom qualifié complet avec la classe |
type | str | Type du champ sous forme de chaîne |
callers | list[JavaMethod] | Méthodes référençant ce champ (paresseux, mis en cache) |
declaring_class | JavaClass | Classe à laquelle ce champ appartient |
java | JObject | Passerelle vers jadx.api.JavaField |
JavaPackage| Propriété | Type | Description |
|---|---|---|
name | str | Nom complet du paquet |
classes | list[JavaClass] | Classes de ce paquet |
sub_packages | list[JavaPackage] | Sous-paquets |
java | JObject | Passerelle vers jadx.api.JavaPackage |
Chaque wrapper expose son objet Java JADX sous-jacent via .java. Cela vous permet d'appeler toute API JADX que nous n'avons pas encore encapsulée :
with Jadx("app.apk") as jadx:
cls = jadx.search_class("com.example.Foo")
# Call JADX Java API directly
code_info = cls.java.getCodeInfo()
pyjadx coexiste avec d'autres consommateurs JPype (par exemple, PyGhidra) dans le même processus. Si une JVM est déjà en cours d'exécution, pyjadx.start() ajoute les JAR JADX au classpath existant. Sinon, elle en démarre une.
import pyghidra
pyghidra.start() # starts JVM for Ghidra
import pyjadx
pyjadx.start() # adds JADX JARs to existing JVM — no conflict
Installation personnalisée de JADX :
# Via environment variable
# export JADX_HOME=/opt/jadx
# Or at runtime
import pyjadx
pyjadx.start(jadx_home="/opt/jadx")
Mise en cache des JAR : Les JAR JADX sont téléchargés automatiquement depuis Maven Central lors de la première utilisation et mis en cache dans ~/.pyjadx/jars/<version>/.
MIT