
JPypeを介したJADXのPythonバインディング。PythonからAndroid APKおよびDEXファイルをJavaソースに逆コンパイルします。
from pyjadx import Jadx
with Jadx("app.apk") as jadx:
for cls in jadx.classes:
print(cls.full_name)
print(cls.code)
JADXは主要なオープンソースAndroidデコンパイラであり、DalvikバイトコードからクリーンなJava/Kotlinソースを生成し、クラス階層、ジェネリクス、例外処理、アノテーションを保持します。pyjadxはこれをサブプロセスオーバーヘッドなしでPythonにもたらします。JADXはJPypeを介してインプロセスで実行されます。
pip install pyjadx
要件: JDK 11以上(JADX JARは初回使用時に自動的にダウンロードされます)。
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")
| 形式 | 例 |
|---|---|
| APK | Jadx("app.apk") |
| DEX | Jadx("classes.dex") |
| Multi-DEX APK | 透過的に処理 — すべてのクラスがマージされます |
Jadx(path, *, threads=None, mode="auto", code_cache=False)メインエントリポイント。コンテキストマネージャとして使用するか、手動でload()/close()を呼び出します。
| パラメータ | 説明 |
|---|---|
path | APKまたはDEXファイルへのパス |
threads | JADXスレッドプールサイズ(None = CPUコア数) |
mode | "auto", "restructure", "simple", または "fallback" |
code_cache | False = インメモリキャッシュ(デフォルト)、True = ディスクバックアップ |
プロパティ:
| プロパティ | 型 | 説明 |
|---|---|---|
classes | list[JavaClass] | すべてのDEXファイルにわたるトップレベルのクラス |
packages | list[JavaPackage] | パッケージレベルのナビゲーション |
class_count | int | トップレベルのクラス数 |
java | JObject | 基盤となるjadx.api.JadxDecompilerへのエスケープハッチ |
メソッド:
| メソッド | 説明 |
|---|---|
load() | クラスをロードして解決(__enter__によって呼び出される) |
close() | リソースを解放(__exit__によって呼び出される) |
decompile_all() | すべてのクラスを積極的に逆コンパイル |
search_class(name) | 完全修飾名でクラスを検索 |
JavaClass| プロパティ | 型 | 説明 |
|---|---|---|
name | str | 短い名前("MainActivity") |
full_name | str | 完全修飾名("com.example.MainActivity") |
package | str | パッケージ名 |
code | str | 逆コンパイルされたJavaソース(遅延、キャッシュ) |
smali | str | Smali逆アセンブリ(遅延、キャッシュ) |
methods | list[JavaMethod] | このクラスのメソッド |
fields | list[JavaField] | このクラスのフィールド |
inner_classes | list[JavaClass] | 内部/匿名クラス |
declaring_class | JavaClass | None | 親クラス(内部クラスの場合) |
top_class | JavaClass | 最も外側のエンクロージングクラス |
dependencies | list[JavaClass] | このクラスが依存するクラス |
is_inner | bool | 内部クラスであるかどうか |
java | JObject | jadx.api.JavaClassへのエスケープハッチ |
JavaMethod| プロパティ | 型 | 説明 |
|---|---|---|
name | str | メソッド名 |
full_name | str | クラスを含む完全修飾名 |
code | str | 逆コンパイルされたソース(遅延、キャッシュ) |
callers | list[JavaMethod] | このメソッドを呼び出すメソッド(遅延、キャッシュ) |
callees | list[JavaMethod] | このメソッドが呼び出すメソッド(遅延、キャッシュ) |
override_related | list[JavaMethod] | 双方向のオーバーライドチェーン |
declaring_class | JavaClass | このメソッドが属するクラス |
java | JObject | jadx.api.JavaMethodへのエスケープハッチ |
JavaField| プロパティ | 型 | 説明 |
|---|---|---|
name | str | フィールド名 |
full_name | str | クラスを含む完全修飾名 |
type | str | フィールド型(文字列) |
callers | list[JavaMethod] | このフィールドを参照するメソッド(遅延、キャッシュ) |
declaring_class | JavaClass | このフィールドが属するクラス |
java | JObject | jadx.api.JavaFieldへのエスケープハッチ |
JavaPackage| プロパティ | 型 | 説明 |
|---|---|---|
name | str | 完全なパッケージ名 |
classes | list[JavaClass] | このパッケージのクラス |
sub_packages | list[JavaPackage] | サブパッケージ |
java | JObject | jadx.api.JavaPackageへのエスケープハッチ |
すべてのラッパーは、.javaを介して基盤となるJADX Javaオブジェクトを公開します。これにより、まだラップされていないJADX APIを呼び出すことができます。
with Jadx("app.apk") as jadx:
cls = jadx.search_class("com.example.Foo")
# Call JADX Java API directly
code_info = cls.java.getCodeInfo()
pyjadxは同じプロセス内で他のJPypeコンシューマ(例:PyGhidra)と共存します。JVMがすでに実行中の場合は、pyjadx.start()が既存のクラスパスにJADX JARを追加します。そうでない場合は、新しいJVMを起動します。
import pyghidra
pyghidra.start() # starts JVM for Ghidra
import pyjadx
pyjadx.start() # adds JADX JARs to existing JVM — no conflict
カスタムJADXインストール:
# Via environment variable
# export JADX_HOME=/opt/jadx
# Or at runtime
import pyjadx
pyjadx.start(jadx_home="/opt/jadx")
JARキャッシュ: JADX JARは初回使用時にMaven Centralから自動ダウンロードされ、~/.pyjadx/jars/<version>/にキャッシュされます。
MIT