
Python bindings per JADX.
Binding Python per JADX tramite JPype. Decompila file APK e DEX Android in codice Java da Python.
from pyjadx import Jadx
with Jadx("app.apk") as jadx:
for cls in jadx.classes:
print(cls.full_name)
print(cls.code)
JADX è il decompilatore open-source leader per Android — produce codice Java/Kotlin pulito dal bytecode Dalvik, preservando gerarchie di classi, generici, gestione delle eccezioni e annotazioni. pyjadx porta tutto questo in Python senza l'overhead dei sottoprocessi: JADX gira in-process tramite JPype.
pip install pyjadx
Requisiti: JDK 11+ (i JAR di JADX vengono scaricati automaticamente al primo utilizzo).
from pyjadx import Jadx
with Jadx("app.apk") as jadx:
# Tutte le classi di primo livello (classi interne tramite cls.inner_classes)
for cls in jadx.classes:
print(cls.full_name, len(cls.methods), "metodi")
# Ricerca per nome completamente qualificato
main = jadx.search_class("com.example.MainActivity")
if main:
print(main.code)
# Decompilazione a livello di metodo
for method in main.methods:
print(f"{method.name}: {method.code}")
# Riferimenti incrociati
for method in main.methods:
print(f"{method.name} chiamato da: {[c.name for c in method.callers]}")
# Navigazione dei pacchetti
for pkg in jadx.packages:
print(pkg.name, len(pkg.classes), "classi")
| Formato | Esempio |
|---|---|
| APK | Jadx("app.apk") |
| DEX | Jadx("classes.dex") |
| APK multi-DEX | Gestito in modo trasparente — tutte le classi unite |
Jadx(path, *, threads=None, mode="auto", code_cache=False)Punto di ingresso principale. Usare come context manager o chiamare load()/close() manualmente.
| Parametro | Descrizione |
|---|---|
path | Percorso del file APK o DEX |
threads | Dimensione del pool di thread di JADX (None = numero di CPU) |
mode | "auto", "restructure", "simple" o "fallback" |
code_cache | False = cache in memoria (valore predefinito), True = cache su disco |
Proprietà:
| Proprietà | Tipo | Descrizione |
|---|---|---|
classes | list[JavaClass] | Classi di primo livello in tutti i file DEX |
packages | list[JavaPackage] | Navigazione a livello di pacchetto |
class_count | int | Numero di classi di primo livello |
java | JObject | Vano tecnico per l'oggetto jadx.api.JadxDecompiler sottostante |
Metodi:
| Metodo | Descrizione |
|---|---|
load() | Carica e risolve le classi (chiamato da __enter__) |
close() | Rilascia le risorse (chiamato da __exit__) |
decompile_all() | Decompila eagermente tutte le classi |
search_class(name) | Trova una classe per nome completamente qualificato |
JavaClass| Proprietà | Tipo | Descrizione |
|---|---|---|
name | str | Nome breve ("MainActivity") |
full_name | str | Nome completamente qualificato ("com.example.MainActivity") |
package | str | Nome del pacchetto |
code | str | Sorgente Java decompilato (lazy, in cache) |
smali | str | Disassemblato Smali (lazy, in cache) |
methods | list[JavaMethod] | Metodi in questa classe |
fields | list[JavaField] | Campi in questa classe |
inner_classes | list[JavaClass] | Classi interne/anonymous |
declaring_class | JavaClass | None | Classe padre (se interna) |
top_class | JavaClass | Classe contenitore più esterna |
dependencies | list[JavaClass] | Classi da cui questa dipende |
is_inner | bool | Se è una classe interna |
java | JObject | Vano tecnico per jadx.api.JavaClass |
JavaMethod| Proprietà | Tipo | Descrizione |
|---|---|---|
name | str | Nome del metodo |
full_name | str | Nome completamente qualificato con classe |
code | str | Sorgente decompilato (lazy, in cache) |
callers | list[JavaMethod] | Metodi che chiamano questo (lazy, in cache) |
callees | list[JavaMethod] | Metodi chiamati da questo (lazy, in cache) |
override_related | list[JavaMethod] | Catena bidirezionale di override |
declaring_class | JavaClass | Classe a cui appartiene il metodo |
java | JObject | Vano tecnico per jadx.api.JavaMethod |
JavaField| Proprietà | Tipo | Descrizione |
|---|---|---|
name | str | Nome del campo |
full_name | str | Nome completamente qualificato con classe |
type | str | Tipo del campo come stringa |
callers | list[JavaMethod] | Metodi che referenziano questo campo (lazy, in cache) |
declaring_class | JavaClass | Classe a cui appartiene il campo |
java | JObject | Vano tecnico per jadx.api.JavaField |
JavaPackage| Proprietà | Tipo | Descrizione |
|---|---|---|
name | str | Nome completo del pacchetto |
classes | list[JavaClass] | Classi in questo pacchetto |
sub_packages | list[JavaPackage] | Sotto-pacchetti |
java | JObject | Vano tecnico per jadx.api.JavaPackage |
Ogni wrapper espone l'oggetto Java JADX sottostante tramite .java. Questo permette di chiamare qualsiasi API JADX non ancora coperta dal wrapper:
with Jadx("app.apk") as jadx:
cls = jadx.search_class("com.example.Foo")
# Chiama direttamente l'API Java di JADX
code_info = cls.java.getCodeInfo()
pyjadx coesiste con altri consumatori JPype (es. PyGhidra) nello stesso processo. Se una JVM è già in esecuzione, pyjadx.start() aggiunge i JAR di JADX al classpath esistente. In caso contrario, ne avvia una.
import pyghidra
pyghidra.start() # avvia la JVM per Ghidra
import pyjadx
pyjadx.start() # aggiunge i JAR di JADX alla JVM esistente — nessun conflitto
Installazione personalizzata di JADX:
# Tramite variabile d'ambiente
# export JADX_HOME=/opt/jadx
# Oppure a runtime
import pyjadx
pyjadx.start(jadx_home="/opt/jadx")
Cache JAR: I JAR di JADX vengono scaricati automaticamente da Maven Central al primo utilizzo e memorizzati nella cache in ~/.pyjadx/jars/<version>/.
MIT