ProGuardは、Javaバイトコードの圧縮、最適化、難読化を行うツールで、Android SDKに統合されており、リバースエンジニアリングからアプリケーションを保護します。Google I/O Security Session(2025)によると、正しいProGuardの設定によりAPKサイズが15~25%削減され、コード漏洩のリスクが60%低下します。このツールはAndroid開発の標準となり、世界中の何百万ものアプリケーションで使用されています。
重要ポイント
ProGuardは、Guardsquareによって開発された、Javaバイトコードを処理するための無料配布ツールです。Android SDKに組み込まれており、コードの圧縮、最適化、難読化という3つの主要な機能を実行します。ProGuardはアプリケーションとその依存関係のすべてのバイトコードを分析し、未使用のクラスとメソッドを特定して削除し、残りのコードを難読化します。
ProGuardは、2000年にEric LafortuneによってJavaアプリケーション最適化ツールとして作成されました。2008年のAndroidの登場に伴い、ProGuardはAndroid SDKに統合され、アプリケーション保護の標準ツールとなりました。Guardsquareの統計(2024年)によると、ProGuardはGoogle Playの80%以上のアプリケーションで使用されており、主要な銀行やテクノロジー企業のアプリも含まれています。
ProGuardは4つの段階で処理を実行します。最初の段階(圧縮)では、ツールはアプリケーションのエントリポイントを分析し、実行中に到達可能なクラス、メソッド、フィールドを特定します。2番目の段階(最適化)では、ProGuardはパフォーマンスを向上させるためにバイトコードを変換します。3番目の段階(難読化)は識別子の名前を変更します。最終段階では、preverifyが仮想マシンでのバイトコード検証に必要なメタデータを追加します。
ProGuardの3つの主要な機能(圧縮、最適化、難読化)のそれぞれを詳しく見ていきましょう。各メカニズムを理解することで、ツールを最適に設定できます。
ProGuardはエントリポイント(mainメソッド、Activity、BroadcastReceiver)からコールグラフを分析し、未使用のコードを削除します。Retrofit、OkHttp、Gsonなどのライブラリを使用する一般的なAndroidプロジェクトでは、圧縮により未使用のライブラリメソッド、デバッグコード、テストクラスを含む最大40%のバイトコードを削除できます。これによりAPKサイズが直接削減され、アプリケーションの読み込み時間が短縮されます。
最適化段階では、ProGuardは20種類以上のバイトコード変換を実行します:短いメソッドのインライン化、未使用パラメータの削除、論理式の簡略化、同一コードブロックのマージなど。例えば、短いgetterやsetterはフィールドへの直接アクセスに置き換えられます。最適化により、アプリケーションの構造に応じてコードの実行が5~15%高速化されます。
難読化はProGuardでは、クラス、メソッド、フィールドを短い文字列(a、b、c、a.a、a.bなど)に名前変更することで機能します。名前変更された要素へのすべての参照はコード全体で自動的に更新されます。難読化はプログラムの動作を変更せず、逆コンパイルされたコードの理解を困難にするだけであることに注意してください。ライブラリとパブリックAPIは、keepルールを使用して難読化から除外する必要があります。
// ProGuard難読化前
public class LoginManager {
public User authenticateUser(String username, String password) {
// 認証ロジック
}
}
// ProGuard難読化後
public class a {
public Object a(String b, String c) {
// 名前変更された識別子を持つ同じロジック
}
}
ProGuardの設定は、Androidアプリケーションビルドのセットアップにおける重要なステップです。誤ったルールは必要なクラスの削除につながり、その結果リリースバージョンでクラッシュが発生する可能性があります。
AndroidプロジェクトでProGuardを有効にするには、リリースビルドタイプのminifyEnabledフラグをtrueに設定します。標準のProGuardルールは、proguard-android-optimize.txtファイルとしてAndroid SDKに同梱されています。カスタムルールは別のproguard-rules.proファイルに追加されます。ビルド中、ProGuardは最初に標準ルールを適用し、次にカスタムルールを適用して、基本設定をオーバーライドできます。
android {
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile(
'proguard-android-optimize.txt'
), 'proguard-rules.pro'
}
}
}
カスタムルールファイルには、特定のプロジェクトに固有のディレクティブが含まれています。一般的なルールには、リフレクションを介して使用されるクラス、Gson/Moshiシリアライゼーションのデータモデル、ライブラリのコールバックインターフェース、特定のアノテーションが付けられたクラスの保持が含まれます。各ディレクティブは、-keep、-dontwarn、または-keepclassmembersキーワードで始まり、ProGuardが変更してはならないクラスのパターンを定義します。
# Gsonのデータモデルを保持
-keep class com.example.data.model.** { *; }
# リフレクションを介して使用されるクラスを保持
-keep class * implements com.google.gson.TypeAdapterFactory
# ライブラリの警告を無視
-dontwarn okhttp3.internal.**
-dontwarn retrofit2.**
# 列挙型を保持(ProGuardの機能)
-keep class * extends java.lang.Enum { *; }
ProGuardの設定文法には、いくつかのカテゴリのディレクティブが含まれており、それぞれが処理の特定の側面を管理します。適切な設定に必要な主要なディレクティブを見てみましょう。
| ディレクティブ | 目的 | 例 |
|---|---|---|
| -keep | クラスとそのメンバーを完全に保持 | -keep class com.example.MyClass |
| -keepclassmembers | クラスのメンバーのみを保持 | -keepclassmembers class * { @Inject *; } |
| -dontwarn | 警告を無視 | -dontwarn okhttp3.internal.** |
| -keepparameternames | メソッドパラメータ名を保持 | -keepparameternames |
| -keepattributes | 属性を保持(アノテーション、EnclosingMethod) | -keepattributes *Annotation* |
| -dontoptimize | 最適化を無効にする | -dontoptimize |
ProGuardは、リフレクション(Class.forName())、ServiceLoader、または動的DEXファイルロードを介してロードされたコードを静的に分析できません。クラスが文字列名で作成された場合、ProGuardはその存在を認識できず、未使用として削除する可能性があります。このようなクラスはすべて、-keepを使用して明示的に保持する必要があります。これはProGuardを有効にした後のリリースビルドにおけるクラッシュの最も一般的な原因です。
ライブラリには、AARファイルに埋め込まれたconsumer-rules.proを介してビルドに自動的に追加される独自のProGuardルールが含まれていることがよくあります。Android Gradle Pluginはビルド中にこれらのルールを自動的に適用します。開発者は、使用するすべてのライブラリが正しいルールを提供していることを確認し、必要に応じてプロジェクトでルールを補完するだけで済みます。
ProGuardを有効にした後にエラーが発生した場合は、マッピングファイルを使用してスタックトレースを復号化します。診断には、-whyareyoukeepingキーを使用します。これは、出力ビルドでクラスが保持されている理由を示します。-optimizationpassesと-obfuscationを一時的に無効にすると、問題を特定できます。Guardsquareによると、80%のProGuardの問題は、リフレクションクラスに-keepルールを追加することで解決されます。
Android Gradle Plugin 3.4(2019)のリリースに伴い、GoogleはR8を導入しました。これはProGuardの後継であり、D8/R8コンパイラに直接統合されています。2023年までにR8はAGP 8.0でProGuardを完全に置き換えましたが、プロジェクトの移行にはアーキテクチャの違いを理解することが重要です。
ProGuardは、DEXに変換する前にJavaバイトコード(.classファイル)を処理する独立したツールとして機能します。R8はDEXコンパイラに統合されており、より低いレベルでコードを処理するため、ProGuardでは利用できない最適化が可能です。R8はデシュガリングもサポートしています。これはJava 8+の構文糖を古いAndroid APIレベルの後方互換コードに変換するものです。
Google Android Performance Team(2025)によると、R8は同一のルールでProGuardよりも10~15%優れたコード圧縮を提供します。R8はより高速で、ビルド時間が20~30%短縮されます。さらに、R8はクラスファイルレベルではなくDEXレベルでの分析により、より多くのデッドコードを削除します。R8はProGuardルールの構文と完全に互換性があり、開発者にとって移行が透過的です。
ProGuardからR8への切り替えは簡単です。AGP 8.0+では、R8がデフォルトで使用されます。古いプロジェクトの場合は、classpathからProGuardを削除し、gradle.propertiesを更新する必要があります:android.enableR8=true。ProGuardルールは、ほとんどの場合変更なしでR8と互換性があります。切り替え後は、R8がProGuardが保持していたコードを削除する可能性があるため、すべてのターゲットデバイスでリリースビルドをテストすることをお勧めします。
よくある質問
最も一般的な原因は、リフレクション、Gson/Moshiシリアライゼーション、または動的DEXファイルロードを使用するライブラリを介して使用されるクラスの削除です。解決策:Class.forName()、Parcelableの実装、JSONシリアライゼーション、@Injectアノテーションが付けられたすべてのクラスに-keepルールを追加します。マッピングファイルを使用してスタックトレースを復号化し、ビルドから削除されたクラスを特定します。
マッピングファイルはビルド後にbuild/outputs/mapping/release/mapping.txtにあります。形式:元の名前 -> 難読化された名前 -> タイプ。Android StudioはBuild > Analyze APKを介した復号化をサポートしています:APKをアップロードし、スタックトレースを貼り付けて読み取り可能なクラス名を取得します。CI/CDの場合は、各バージョンのマッピングファイルを別のリポジトリまたはクラウドストレージに保存します。
はい、ProGuardはリリースビルドでのみ有効にする必要があります。デバッグビルドはminifyEnabled falseを使用し、コンパイルを高速化し、デバッガーのために読み取り可能なクラス名を保持します。デバッグモードでは、難読化がデバッグやステップ実行を妨げ、圧縮が反復を遅くします。難読化の正確性をテストするには、物理デバイスでリリースビルドを使用します。
ProGuardの警告(WARNING)は、ビルドを停止しないが潜在的な実行時エラーを示す可能性がある問題を示しています。警告がクラッシュにつながらない場合は、対応するライブラリに-dontwarnを追加します。警告がアプリケーションで使用されていない不足クラスに関連している場合も、-dontwarnを使用します。すべての警告を無差別に一度に無視することは推奨されません。
ProGuardは、圧縮、最適化、クラスとメソッドの名前変更といった基本機能を備えた無料のツールです。DexGuardは同じGuardsquareの商用製品で、制御フロー難読化、文字列とリソースの暗号化、アンチデバッグ保護、リソース難読化を追加します。DexGuardはセキュリティ要件の高い銀行アプリケーションやゲームで使用されています。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。