# ProGuard: Java bytecode shrinking, optimization and obfuscation

> ProGuard removes unused classes, fields and methods from Java bytecode, then renames what remains. It is a build-time tool for JVM and Android artifacts, and its main cost is the keep-rule work that follows.

**Guardsquare/proguard** — ProGuard, Java optimizer and obfuscator

- Repository: https://github.com/Guardsquare/proguard
- Website: https://www.guardsquare.com/en/products/proguard
- Stars: 3,666 · Forks: 486
- Language: Java
- License: GPL-2.0
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/guardsquare-proguard

## What ProGuard removes and who ends up maintaining the rules

ProGuard is a free shrinker, optimizer, obfuscator and preverifier for Java bytecode. The README describes three jobs: detecting and removing unused classes, fields, methods and attributes; optimizing bytecode and removing unused instructions; and renaming the remaining classes, fields and methods with short meaningless names. The stated result is smaller and faster applications and libraries.

The audience is narrower than the description suggests. Anyone who ships a jar, an aar or an Android app can run it, but the work does not stop at the first successful build. Shrinking is only safe when ProGuard knows which entry points must survive. Reflection, service loaders, serialization and framework callbacks are reached by name at runtime, and the shrinker cannot see those edges in the bytecode. Every such edge becomes a keep rule in the configuration file. That file, not the ProGuard version, is what a team maintains over time.

The README is explicit that most options belong in a configuration file rather than on the command line. That is a fair signal about the shape of the tool: it is configured, not scripted ad hoc. The manual's configuration section is where the option set lives, and the repository ships examples for Ant, Gradle, Kotlin applications, Spring Boot and Android plugin setups under examples/.

## How shrinking, optimization and renaming actually run

ProGuard reads input jars (injars) and library jars (libraryjars), computes what is reachable, and writes a processed output jar (outjars). The library jars matter more than they look: they are the external API surface ProGuard is not allowed to modify but must account for when deciding what is used. Get that set wrong and the shrinker either keeps too much or removes something the runtime needs.

The pipeline is ordered. Shrinking runs before optimization, so dead methods are gone before inlining and constant propagation consider the survivors. Renaming comes last, which is why obfuscated stack traces need a mapping file to be readable again. The repository includes a retrace/ directory, and the README's own feature list mentions removing logging code from applications and their libraries without changing, or even having, the source.

The README gives size and speed expectations with unusual honesty. Optimizations typically reduce application size by anything between 20% and 90%, with the reduction depending mostly on how much of the external libraries ProGuard can remove in whole or in part. Performance may improve by up to 20%, but the README notes that on server and desktop JVMs the difference generally is not noticeable. That second sentence is the useful one. If your motivation is throughput on a server, the size argument is the stronger case.

## Installing ProGuard and running a first configuration

The README points to GitHub releases for the latest download. Unpack it and the bin directory holds the launchers. On Linux or macOS the entry point is a shell script, and on Windows a batch file. The README's own example passes a configuration file with the @ prefix rather than listing options inline.

```bash
bin/proguard.sh @myconfig.pro
```

The configuration file is where injars, libraryjars, outjars and keep rules belong. The README does not print a complete starter file, so the option names to use are the ones documented in the manual's configuration section.

For a Gradle build, the README shows adding the plugin to the buildscript classpath so Gradle can find the task at build time. This downloads ProGuard from Maven Central.

```Groovy
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.guardsquare:proguard-gradle:7.10.0'
    }
}
```

A task then points at a configuration file, declares the input jar, declares the runtime as a library jar, and names the output. The README's example handles the JDK split explicitly, which is worth copying rather than reinventing.

```Groovy
tasks.register('proguard', ProGuardTask) {
    configuration file('proguard.pro')
    injars(tasks.named('jar', Jar).flatMap { it.archiveFile })
    if (System.getProperty('java.version').startsWith('1.')) {
        libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
    } else {
        libraryjars "${System.getProperty('java.home')}/jmods/java.base.jmod", jarfilter: '!**.jar', filter: '!module-info.class'
    }
    verbose
    outjars(layout.buildDirectory.file("libs/${baseCoordinates}-minified.jar"))
}
```

Building ProGuard itself needs a Java 8 JDK. The README gives ./gradlew assemble, with artifacts landing in the lib directory, and ./gradlew publishToMavenLocal for a local Maven repository.

## Where ProGuard breaks: reflection, keep rules and mapping files

The failure mode is predictable. Code that is only reachable by name at runtime looks unused to the shrinker, so it is removed or renamed, and the failure appears at runtime rather than at build time. The fix is a keep rule, and the README does not enumerate the reflection patterns that need one; the manual covers configuration in detail, and the repository's examples directory is where the practical patterns for Ant, Gradle, Spring Boot and Android live.

The second cost is the mapping file. Obfuscated stack traces are unreadable without it, which is why retrace/ exists in the repository. If your process does not archive the mapping file alongside each release, you lose the ability to read production crashes from that build. This is a release-engineering obligation, not a ProGuard setting.

The third case where ProGuard is the wrong tool is licence fit. The README states ProGuard is released under the GNU General Public License, version 2, with exceptions granted to a number of projects, documented in docs/md/manual/license/gplexception.md. If you distribute a closed application, that exception list is the first thing to read, and whether your distribution model fits is a question for your own counsel. ProGuard the open source project and the commercial products on the Guardsquare homepage are separate things; the README describes the former.

## R8 versus ProGuard: same goal, different pipeline

The realistic alternative for Android builds is R8, the shrinker integrated into the Android Gradle Plugin toolchain. The difference is not the goal, which is the same: shrink, optimize and rename. It is where the tool sits. ProGuard is a separate program with its own configuration file and its own task, which the README shows wiring into Gradle by hand, including the libraryjars entry for the JDK. R8 runs inside the Android build pipeline, so the platform's own rules and defaults apply without you assembling the runtime classpath yourself.

That integration is why ProGuard's Android examples exist in this repository at all: the tool predates the integrated pipeline and still supports it. The trade-off runs both ways. A standalone ProGuard task gives you explicit control over injars, libraryjars and outjars, which matters when the artifact is not an Android app: a plain jar, a library, a Spring Boot application. Inside an Android build, that same explicitness is mostly overhead.

For non-Android JVM artifacts the comparison is less about a direct competitor and more about whether shrinking is worth the rule maintenance at all. If your jar is small and distributed internally, the 20% to 90% range the README cites is a range, not a promise, and it depends on how much third-party code you pull in.

## Release cadence, licence and what upgrades cost

The repository is not archived, and the most recent release listed is v7.10.0 on 2026-08-24, with v7.9.1 on 2026-04-09 and v7.9 on 2026-03-18 before it. Releases arrive on a regular cadence, so the version pin in your buildscript is a moving target you will revisit.

The upgrade cost is not the ProGuard version bump. It is the interaction between a new version's optimization behavior and your keep rules. A rule that was unnecessary under one version can become necessary under another, and the symptom is a runtime failure rather than a compile error. The README does not document a rollback procedure, so the practical safeguard is pinning the exact version in the buildscript classpath and testing the processed artifact before release.

On licensing: ProGuard is GPL-2.0 with exceptions granted to a number of projects, listed in docs/md/manual/license/gplexception.md. The README does not state which projects those are or what the exception terms are, so read that file rather than inferring. Note the copyright line in the README, which reads 2002-2025 Guardsquare NV. This is a description of the licence terms as published, not legal advice; whether your distribution model is compatible is a question for a lawyer.

## Conclusion

ProGuard fits teams shipping Java or Android artifacts where unused code, readable identifiers or both are a problem, and who can maintain a keep-rule file as part of the build. It is the wrong tool if you build a closed application and want to avoid GPL-2.0 obligations, or if you cannot reproduce a failing build from the same configuration file. Before adopting it, verify three things on your own artifact: that the Gradle plugin resolves com.guardsquare:proguard-gradle at the version you intend to pin, that your libraryjars entry matches your JDK layout (rt.jar before Java 9, jmods from Java 9 onward), and that the resulting jar still passes your tests after renaming. The keep rules are the artifact that will need attention on every release, not the ProGuard version number.

## FAQ

### What is ProGuard used for?

It detects and removes unused classes, fields, methods and attributes from Java bytecode, optimizes the bytecode that remains, and renames the surviving classes, fields and methods with short meaningless names. The README states the resulting applications and libraries are smaller and faster.

### How much does ProGuard cost?

The README describes ProGuard as free and states it is released under the GNU General Public License, version 2, with exceptions granted to a number of projects. The commercial products listed on the Guardsquare homepage are separate from the open source project documented in this repository.

### How do I install ProGuard?

Download the latest release from GitHub releases and use the launchers in the bin directory, or add com.guardsquare:proguard-gradle to the buildscript classpath in build.gradle to run it as a Gradle task. Building from source requires a Java 8 JDK and ./gradlew assemble.

### How do I use ProGuard for a Java application?

The README shows putting the options in a configuration file and invoking bin/proguard.sh @myconfig.pro on Linux or macOS, or bin\proguard.bat @myconfig.pro on Windows. The configuration declares input jars, library jars, output jars and keep rules, with the full option set in the manual's configuration section.

### How do I use ProGuard to obfuscate a jar?

Renaming is one of the three jobs ProGuard performs, alongside shrinking and optimization, and it applies to the classes, fields and methods that survive shrinking. The input and output are declared as injars and outjars, so the obfuscated result is written to the output jar you name.

## Sources

- [Guardsquare/proguard on GitHub](https://github.com/Guardsquare/proguard)
- [License: GPL-2.0](https://github.com/Guardsquare/proguard/blob/master/LICENSE)
- [Project website](https://www.guardsquare.com/en/products/proguard)
- [README](https://github.com/Guardsquare/proguard/blob/master/README.md)
- [Releases](https://github.com/Guardsquare/proguard/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/guardsquare-proguard
