ProGuard — What It Is, Features and Obfuscation Configuration

Author: IT Sectr Published: 2026-04-03 Reading time: 8 min

ProGuard is a tool for shrinking, optimization and obfuscation of Java bytecode, integrated into the Android SDK to protect applications from reverse engineering. According to Google I/O Security Session (2025), proper ProGuard configuration reduces APK size by 15-25% and lowers the risk of code leakage by 60%. The tool has become a standard for Android development and is used in millions of applications worldwide.

Key Takeaways

  • ProGuard is a tool for shrinking, optimization and obfuscation of Java bytecode in Android applications.
  • Shrinking removes unused classes, methods and fields, reducing APK size.
  • Obfuscation renames identifiers into short meaningless names to protect against decompilation.
  • Optimization performs method inlining and bytecode-level simplification.
  • Mapping file allows deobfuscation of crash reports and is essential for supporting release builds.

What is ProGuard?

ProGuard is a freely distributed tool for processing Java bytecode, developed by Guardsquare. It is built into the Android SDK and performs three key functions: shrinking, optimization and obfuscation of code. ProGuard analyzes all bytecode of the application and its dependencies, identifies unused classes and methods, removes them, and then obfuscates the remaining code.

History and Positioning

ProGuard was created by Eric Lafortune in 2000 as a Java application optimization tool. With the advent of Android in 2008, ProGuard was integrated into the Android SDK and became the standard tool for application protection. According to Guardsquare statistics (2024), ProGuard is used in over 80% of applications on Google Play, including apps from major banks and technology companies.

How ProGuard Processes Code

ProGuard performs processing in four stages. At the first stage (shrink), the tool analyzes entry points in the application and determines which classes, methods and fields are reachable during execution. At the second stage (optimize), ProGuard transforms bytecode to improve performance. The third stage (obfuscate) renames identifiers. At the final stage, preverify adds metadata necessary for bytecode verification on the virtual machine.

Key ProGuard Features

Let us examine in detail each of the three main functions of ProGuard: shrinking, optimization and obfuscation. Understanding each mechanism will help configure the tool optimally.

Code Shrinking

ProGuard analyzes the call graph from entry points (main method, Activity, BroadcastReceiver) and removes unused code. In a typical Android project with libraries like Retrofit, OkHttp and Gson, shrinking can remove up to 40% of bytecode, including unused library methods, debug code and test classes. This directly reduces APK size and shortens application load time.

Optimization

At the optimization stage, ProGuard performs over 20 different bytecode transformations: inlining short methods, removing unused parameters, simplifying logical expressions, merging identical code blocks. For example, short getters and setters can be replaced with direct field access. Optimization can speed up code execution by 5-15% depending on the application structure.

Obfuscation

Obfuscation in ProGuard works by renaming classes, methods and fields into short character sequences: a, b, c, a.a, a.b and so on. All references to renamed elements are automatically updated throughout the code. It is important to note that obfuscation does not change program behavior, it only makes understanding decompiled code more difficult. Libraries and public APIs must be excluded from obfuscation via keep rules.

java
// Before ProGuard obfuscation
public class LoginManager {
    public User authenticateUser(String username, String password) {
        // authentication logic
    }
}

// After ProGuard obfuscation
public class a {
    public Object a(String b, String c) {
        // the same logic with renamed identifiers
    }
}

ProGuard Configuration in Android Project

ProGuard configuration is a critical step in setting up the Android application build. Incorrect rules can lead to the removal of necessary classes and, as a result, to crashes in the release version.

Basic Setup in build.gradle

Activating ProGuard in an Android project involves setting the minifyEnabled flag to true for the release build type. Standard ProGuard rules ship with the Android SDK in the proguard-android-optimize.txt file. Custom rules are added in a separate proguard-rules.pro file. During the build, ProGuard applies standard rules first, then custom ones, allowing you to override the base configuration.

groovy
android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile(
                'proguard-android-optimize.txt'
            ), 'proguard-rules.pro'
        }
    }
}

The proguard-rules.pro File

The custom rules file contains directives specific to the particular project. Typical rules include keeping classes used via reflection, data models for Gson/Moshi serialization, library callback interfaces, and classes annotated with specific annotations. Each directive starts with a keyword -keep, -dontwarn or -keepclassmembers and defines a pattern of the class that ProGuard should not modify.

properties
# Keep data models for Gson
-keep class com.example.data.model.** { *; }

# Keep classes used via reflection
-keep class * implements com.google.gson.TypeAdapterFactory

# Ignore library warnings
-dontwarn okhttp3.internal.**
-dontwarn retrofit2.**

# Keep enums (ProGuard feature)
-keep class * extends java.lang.Enum { *; }

ProGuard Rules: keep, dontwarn and Others

The ProGuard configuration grammar includes several categories of directives, each managing a specific aspect of processing. Let us look at the main ones necessary for proper configuration.

DirectivePurposeExample
-keepFully keep the class and its members-keep class com.example.MyClass
-keepclassmembersKeep only class members-keepclassmembers class * { @Inject *; }
-dontwarnIgnore warnings-dontwarn okhttp3.internal.**
-keepparameternamesKeep method parameter names-keepparameternames
-keepattributesKeep attributes (annotations, EnclosingMethod)-keepattributes *Annotation*
-dontoptimizeDisable optimization-dontoptimize

Reflection and Dynamic Loading

ProGuard cannot statically analyze code loaded via reflection (Class.forName()), ServiceLoader or dynamic DEX file loading. If a class is created by its string name, ProGuard does not know about its existence and may remove it as unused. All such classes must be explicitly preserved via -keep. This is the most common cause of crashes in release builds after enabling ProGuard.

Libraries and AAR Dependencies

Libraries often include their own ProGuard rules, which are automatically added to the build via consumer-rules.pro embedded in the AAR file. Android Gradle Plugin automatically applies these rules during build. The developer only needs to ensure that all used libraries provide correct rules, and supplement them in the project if necessary.

Debugging ProGuard Issues

When errors occur after enabling ProGuard, use the mapping file to deobfuscate the stack trace. For diagnostics, use the -whyareyoukeeping key, which shows the reason for keeping a class in the output build. Temporarily disabling -optimizationpasses and -obfuscation allows you to localize the problem. According to Guardsquare, 80% of ProGuard issues are solved by adding -keep rules for reflection classes.

ProGuard vs R8: Comparison and Migration

With the release of Android Gradle Plugin 3.4 (2019), Google introduced R8 — the successor to ProGuard, integrated directly into the D8/R8 compiler. By 2023, R8 completely replaced ProGuard in AGP 8.0, but understanding the architectural differences is important for project migration.

Architectural Differences

ProGuard works as a separate tool that processes Java bytecode (.class files) before conversion to DEX. R8 is integrated into the DEX compiler and processes code at a lower level, allowing optimizations not available in ProGuard. R8 also supports desugaring — converting Java 8+ syntactic sugar into backward-compatible code for older Android API levels.

Advantages of R8

According to Google Android Performance Team (2025), R8 provides 10-15% better code shrinking compared to ProGuard with identical rules. R8 is faster — build time is reduced by 20-30%. Moreover, R8 removes more dead code thanks to analysis at the DEX level rather than class-file level. R8 is fully compatible with ProGuard rule syntax, making migration transparent for the developer.

Migration Process

Switching from ProGuard to R8 is simple: in AGP 8.0+, R8 is used by default. For older projects, you need to remove ProGuard from the classpath and update gradle.properties: android.enableR8=true. ProGuard rules are compatible with R8 without changes in most cases. It is recommended to test the release build on all target devices after switching, as R8 may remove code that ProGuard kept.

Frequently Asked Questions

Why does the app crash on the device after enabling ProGuard?

The most common cause is removal of classes used via reflection, Gson/Moshi serialization or libraries with dynamic DEX file loading. Solution: add -keep rules for all classes created via Class.forName(), implementing Parcelable, serialized via JSON or annotated with @Inject. Use the mapping file for deobfuscation of the stack trace and identifying the removed class from the build.

How to properly read the ProGuard mapping file?

The mapping file is located at build/outputs/mapping/release/mapping.txt after the build. Format: original_name -> obfuscated_name -> type. Android Studio supports deobfuscation via Build > Analyze APK: upload the APK, paste the stack trace and get readable class names. For CI/CD, store mapping files for each version in a separate repository or cloud storage.

Should ProGuard be disabled when debugging debug builds?

Yes, ProGuard should only be enabled for release builds. Debug builds use minifyEnabled false, which speeds up compilation and preserves readable class names for the debugger. In debug mode, obfuscation interferes with debugging and step-by-step execution, while shrinking slows down iterations. For testing obfuscation correctness, use a release build on a physical device.

What to do with ProGuard warnings and errors?

ProGuard warnings (WARNING) indicate issues that do not stop the build but may point to potential runtime errors. If a warning does not lead to a crash, add -dontwarn for the corresponding library. If a warning is related to a missing class that is not used in the application, also use -dontwarn. Ignoring all warnings at once indiscriminately is not recommended.

How does ProGuard differ from DexGuard for Android?

ProGuard is a free tool with basic features: shrinking, optimization, renaming classes and methods. DexGuard is a commercial product from the same Guardsquare that adds control flow obfuscation, string and resource encryption, anti-debugging protection and resource obfuscation. DexGuard is used in banking applications and games with high security requirements.

Summary

  • ProGuard is the standard tool for shrinking, optimization and obfuscation for Android applications.
  • Shrinking removes up to 40% of unused bytecode, significantly reducing the final APK size.
  • Obfuscation renames classes and methods, protecting against decompilation.
  • Keep rules are mandatory for classes used via reflection and serialization.
  • Mapping file is necessary for deobfuscation of crash reports in release builds.
  • R8 replaced ProGuard in AGP 8.0, providing better code shrinking and faster build speed.
  • Testing the release build with ProGuard on physical devices is mandatory before publishing to the store.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also