Claude CodeでR8の難読化をretraceで戻してから渡す手順
Play Consoleやlogcatの難読化されたスタックトレースを、mapping.txtとretraceで戻してからClaude Codeに渡す順序。keepルールを足したあとの検証まで、AndroidのR8を例にまとめます。
R8で難読化したAndroidアプリのクラッシュログは、そのままClaude Codeに貼ると調査の質が落ちます。a.b.a.c(Unknown Source) のような名前では、Claudeもリポジトリ内のどのクラスか特定できないからです。先に mapping.txt と retrace で元の名前に戻し、戻したトレースを渡す。この順序なら、Claudeは元のクラス名を手がかりにリポジトリを調べられます。
keepルールを足したあとの検証まで含めて、Claude Codeに任せる範囲と人が握る範囲を分けて書きます。
なぜ貼る前に戻すのか
R8は、コードの縮小に加えて名前の短縮もします。com.example.MyActivity が a.b.a になるのが典型例で、DEXファイルが小さくなる代わりに、スタックトレースはソースと対応しなくなります。行番号やクラス名、メソッド名が変わるため、トレースだけではコードを引けません。
Claude Codeにバグ修正を頼むときは、再現コマンドとスタックトレースを渡すと進みやすくなります。これはClaude Codeの一般的なワークフロー解説にも書かれている基本です。難読化されたままのトレースは、この「手がかり」として働きません。リポジトリを検索しても a.b.a に当たる箇所が見つからず、推測で別のクラスを疑い始める恐れがあります。
戻してから渡せば、Claudeは元のクラス名で検索し、該当ファイルを開いて原因を読めます。
戻す手段は3つある
どの経路でもmappingファイル(mapping.txt)が材料になります。使う場面が違うだけです。
スタックトレースを戻す3つの経路
Logcat(Android Studio)
Android Studio Otter 3 Feature DropとAGP 9.0以降は、Logcatが自動でデオブフスケートします。手元の端末や実機デバッグの出力はこれで足ります。
retraceコマンド
古いAndroid Studioを使っている場合や、ログファイルを手元に持っている場合の手動手段です。コマンドラインツールに同梱されています。
Play Console
mappingをアップロードしておくと、以降のクラッシュとANRがデオブフスケートされた状態で、Android vitalsの画面に出ます。
Claude Codeに渡す素材として使いやすいのは、手元のファイルに落とせる retrace の出力です。Play Consoleの画面からトレースをコピーする場合も、すでに戻っているかどうかを先に見ておくと無駄がありません。
retraceの実行手順
retraceは、mappingファイルとスタックトレースのファイルを引数に取ります。Android開発者向けドキュメントに載っているコマンドは次の形です。
$ANDROID_HOME/cmdline-tools/latest/bin/retrace \
app/build/outputs/mapping/$releaseVariant/mapping.txt \
trace.txt$releaseVariant はビルドバリアントの名前(たとえば release)に置き換えます。trace.txt には、Play Consoleやクラッシュ収集サービスからコピーした難読化済みのトレースを貼ります。
トレースをClaude Codeに渡すまでの流れ
- 1
クラッシュしたバージョンのmapping.txtを探す
クラッシュが出たリリースと同じビルドのmappingを使います。別のビルドのmappingでは名前が合いません。
- 2
トレースをtrace.txtに保存する
Play ConsoleやCrashlyticsの画面から、難読化されたままのスタックトレースをコピーして保存します。
- 3
retraceで元の名前に戻す
上のコマンドを実行します。出力の先頭付近で、自分のパッケージ名のクラスが読めることを確かめます。
- 4
戻したトレースをClaude Codeに渡す
再現手順と、戻したトレースを一緒に渡します。
ターミナルから非対話で渡すなら、出力をファイルに保存してパイプで流す形が使えます。Claude Codeは標準入力を受け取れるので、git log を渡す例と同じ要領です。
cat retraced.txt | claude -p \
"このスタックトレースの原因を、リポジトリのコードを読んで特定して"対話セッションで頼むなら、ファイルのパスを書くだけで足ります。
retraced.txt は release 1.4.2 で出たクラッシュを retrace で戻したものです。
該当クラスを開き、nullになる経路を調べてください。mappingは毎回保存しないと戻せない
この作業で一番つまずきやすいのは、mappingが残っていないことです。Android Studioは build/outputs/mapping/ にmappingファイルを保存しますが、ビルドのたびに上書きされます。リリースのたびにコピーを残しておかないと、過去のバージョンのクラッシュは戻せなくなります。
Play Consoleの側にも似た条件があります。
- mappingはバージョンごとに必要で、新しいバージョンのたびにアップロードします
- Android App BundleをAGP 4.1以降でビルドしている場合、アップロードは不要で、Play側がバンドルからmappingを取り出します
- APKで配布している場合は、手動でアップロードします
- アップロード前に起きたクラッシュは、あとからmappingを上げてもデオブフスケートされません
- 対応するのはReTrace互換のmappingで、ProGuardとR8が出す形式です
Claude Codeに「mappingを探して」と頼む前に、保管場所を決めておくと運用が楽です。CIでリリースビルドを作っているなら、成果物としてバージョン名付きで保存する設定が現実的です。
落とし穴
手元のmapping.txtが古いビルドのもの
直近のローカルビルドで mapping.txt が上書きされ、クラッシュが出たリリースの名前と合わなくなります。名前が合わないmappingでは正しく戻せません。リリースごとに保存したコピーを使ってください。
CLAUDE.mdに書いておくと毎回の説明が減る
戻す手順を毎回口頭で伝えるのは手間です。難読化に関する約束事は、CLAUDE.mdに短く書いておけます。
## 難読化されたクラッシュの扱い
- スタックトレースの名前が a.b.a のように短いときは、調査を始めず先に伝えること
- mapping は releases/<バージョン>/mapping.txt にある
- 戻すときは $ANDROID_HOME/cmdline-tools/latest/bin/retrace を使う
- 戻したトレースは retraced.txt に保存してから読むこの断片はあくまで一例で、ディレクトリ名はプロジェクトに合わせて変えてください。要点は、Claudeが難読化済みのトレースを見て推測に走らないよう、止まる条件を書いておくことです。
keepルールを足すときの順序
戻したトレースが ClassNotFoundException や NoSuchMethodException で終わっていたら、リフレクションが壊れている可能性があります。R8の公式ドキュメントでは、次のような例外が目印とされています。
ClassNotFoundExceptionNoSuchMethodExceptionNoSuchFieldExceptionNoClassDefFoundErrorNoSuchMethodErrorNoSuchFieldError
コード側に Class.forName(...) や java.lang.reflect.* の利用があれば、疑いは濃くなります。対処はkeepルールの追加で、自分のコードのリフレクションならJetpack Keepのアノテーションで済ませる手もあります。
Claude Codeにkeepルールを書かせるときは、広く保持するルールを最初に書かせないことが肝心です。-keep class com.example.** { *; } のように広くすれば直りますが、R8の最適化の効果が薄れます。対象を絞った形の例は、次のようになります。
-keep class com.example.model.UserData {
public java.lang.String getUserId();
}これはドキュメントにあるメソッド指定の例です。コンストラクターは <init> で指定します。
ルールの効き方を確かめる
ルールを足したら、効いているかを検証します。ここはClaudeの推測に任せず、R8自身の出力を根拠にします。
keepルール追加後の切り分け
- 1
リリースビルドを作り直して再現する
同じ例外が出なければ直っています。出るなら次へ進みます。
- 2
ルールが取り込まれているかを見る
app/build/outputs/mapping/configuration.txtには、ライブラリとモジュールの全ルールが統合されて載ります。足したルールがここにあるかを確かめます。ライブラリ側が持ち込んだ範囲の広いkeepルールも同じ場所で見つかるので、必要以上に多くのコードが残る原因を探すときの手がかりになります。 - 3
保持理由を調べる
対象のクラスやメソッドが残っている理由を、
-whyareyoukeepingでローカルに調べます。
-whyareyoukeeping はR8に「なぜこれを残したのか」を出力させるルールです。出力には、キープしているルールの場所や、保持されたコードからの参照が載ります。
-whyareyoukeeping class com.example.foo.MainActivity {
private void setLabel(...);
}このルールはローカルでのデバッグ専用で、ビルドが遅くなるためコミットには含めません。Claudeに頼むときも、「一時的に足して、確認後に消す」と指示しておくと混ざりません。
手を動かす前に決めておく役割分担
自動化できるのは調査までで、リリース判断は人が持つのが安全です。
| 作業 | Claude Codeに任せる | 人が握る |
|---|---|---|
| retrace実行と結果の読解 | Claude Codeに任せる向く | 人が握るmappingの正しさの確認 |
| 原因クラスの特定 | Claude Codeに任せる向く | 人が握る再現手順の提供 |
| keepルール案の作成 | Claude Codeに任せる向く | 人が握る範囲の広さの判断 |
-whyareyoukeeping の実行と解釈 | Claude Codeに任せる向く | 人が握るルールをコミットに残さない確認 |
| Play Consoleへのアップロード | Claude Codeに任せる向かない | 人が握るmappingの管理 |
Android端末の操作そのものを任せたい場合は、Android-MCPの手順や、ビルドと画面操作までつなぐReplicant MCPの記事が参考になります。クラッシュ調査全般の渡し方は、Claude Codeデバッグの精度を決める情報の質に整理されています。
まとめ
順序は「mappingを保管する、retraceで戻す、戻したトレースを渡す、keepルールは狭く足して検証する」です。難読化済みのトレースを貼っても、Claudeは調査を始められません。Play Consoleが自動で戻してくれる範囲も、アップロード後のクラッシュに限られます。まずは次のリリースから、mappingをバージョン名付きで残す運用に切り替えるところが出発点になります。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。
- developer.android.com/topic/performance/app-optimization/troubleshoot-the-optimi…
- developer.android.com/topic/performance/app-optimization/add-keep-rules
- developer.android.com/topic/performance/app-optimization/troubleshooting-rules
- support.google.com/googleplay/android-developer/answer/9848633
- developer.android.com/build/shrink-code
- code.claude.com/docs/en/common-workflows