ProGuard manual

    Configuration - Optimizations

    The optimization step of ProGuard can be switched off with the -dontoptimize option. For more fine-grained control over individual optimizations, experts can use the -optimizations option, with a filter based on the optimization names listed below. The filter works like any filter in ProGuard.

    The following wildcards are supported:

    Wildcard Meaning
    ? matches any single character in an optimization name.
    * matches any part of an optimization name.

    An optimization that is preceded by an exclamation mark '!' is excluded from further attempts to match with subsequent optimization names in the filter. Make sure to specify filters correctly, since they are not checked for potential typos.

    For example, "code/simplification/variable,code/simplification/arithmetic" only performs the two specified peephole optimizations.

    For example, "!method/propagation/*" performs all optimizations, except the ones that propagate values between methods.

    For example, "!code/simplification/advanced,code/simplification/*" only performs all peephole optimizations.

    Some optimizations necessarily imply other optimizations. These are then indicated. Note that the list is likely to change for newer versions, as optimizations are added and reorganized.

    Optimizes usages of the Gson library, whenever possible. See Gson optimization for more details.
    Marks classes as final, whenever possible.
    Simplifies enum types to integer constants, whenever possible.
    Merges classes vertically in the class hierarchy, whenever possible.
    Merges classes horizontally in the class hierarchy, whenever possible.
    Merges wrapper classes with their wrapped classes, whenever possible.
    (⇒ code/removal/advanced)
    Removes write-only fields.
    Marks fields as private, whenever possible.
    Generalizes the classes of field accesses, whenever possible.
    Specializes the types of fields, whenever possible
    (⇒ code/simplification/advanced)
    Propagates the values of fields across methods.
    Marks methods as private, whenever possible (devirtualization).
    (⇒ code/removal/advanced)
    Marks methods as static, whenever possible (devirtualization).
    Marks methods as final, whenever possible.
    Unmarks methods as synchronized, whenever possible.
    (⇒ code/removal/advanced)
    Removes unused method parameters.
    Generalizes the classes of method invocations, whenever possible.
    Specializes the types of method parameters, whenever possible.
    Specializes the types of method return values, whenever possible.
    (⇒ code/simplification/advanced)
    Propagates the values of method parameters from method invocations to the invoked methods.
    (⇒ code/simplification/advanced)
    Propagates the values of method return values from methods to their invocations.
    Inlines short methods.
    Inlines methods that are only called once.
    Simplifies tail recursion calls, whenever possible.
    Merges identical blocks of code by modifying branch targets.
    Performs peephole optimizations for variable loading and storing.
    Performs peephole optimizations for arithmetic instructions.
    Performs peephole optimizations for casting operations.
    Performs peephole optimizations for field loading and storing.
    (⇒ code/removal/simple)
    Performs peephole optimizations for branch instructions.
    Performs peephole optimizations for object instantiation.
    Performs peephole optimizations for constant strings.
    Performs peephole optimizations for Math method calls.
    (best used with code/removal/advanced)
    Simplifies code based on control flow analysis and data flow analysis.
    (⇒ code/removal/exception)
    Removes dead code based on control flow analysis and data flow analysis.
    (⇒ code/removal/exception)
    Removes dead code based on a simple control flow analysis.
    Removes unused variables from the local variable frame.
    Removes exceptions with empty try blocks.
    Optimizes variable allocation on the local variable frame.

    ProGuard also provides some unofficial settings to control optimizations, that may disappear in future versions. These are Java system properties, which can be set as JVM arguments (with -D...):

    maximum.inlined.code.length (default = 8 bytes)
    Specifies the maximum code length (expressed in bytes) of short methods that are eligible to be inlined. Inlining methods that are too long may unnecessarily inflate the code size.
    maximum.resulting.code.length (default = 8000 bytes for JSE, 2000 bytes for JME)
    Specifies the maximum resulting code length (expressed in bytes) allowed when inlining methods. Many Java virtual machines do not apply just-in-time compilation to methods that are too long, so it's important not to let them grow too large.

    Aggressive optimization

    ProGuard provides the -optimizeaggressively option. If set, this enables more aggressive assumptions during optimization. This might lead to improved performance and/or reduced code size, but might result in different behavior in rare cases. For example, reading from an array might cause an ArrayIndexOutOfBoundsException to be thrown. Strictly speaking, this means that such an instruction can have a side effect. If this instruction is removed during optimization, the code will thus behave differently under specific circumstances. By default, such instructions are always preserved. Setting this option will lead to these instructions being candidates for removal during optimization. Additionally, class merging is only enabled when this option is set.

    Gson optimization

    ProGuard optimizes Gson code by detecting which domain classes are serialized using the Gson library. It replaces the reflection-based implementation of GSON for reading and writing fields with injected and optimized code that accesses the fields of the domain classes directly when reading and writing JSON. The benefits of this optimization are the following:

    • Domain classes used in conjunction with GSON can be freely obfuscated.
    • The injected serialization code gives better performance compared to the GSON implementation, which relies on reflection.
    • Less configuration is needed as the optimization automatically keeps classes and fields that are required for serialization.


    The Gson optimization is enabled by default and doesn't require any additional configuration, as long as the application code doesn't use unsupported Gson features(see Known limitations).

    Known limitations

    ProGuard can not optimize the following use cases of Gson:

    • Serializing classes containing one of the following Gson annotations:
      • @JsonAdapter
      • @Since
      • @Until
    • Serializing classes that have generic type variables in their signature.
    • Serializing classes using a Gson instance that was built with one of the following settings on the GsonBuilder:
      • excludeFieldsWithModifier
      • setFieldNamingPolicy

    When one of the above Gson features is used, ProGuard automatically preserves the original Gson implementation for all affected domain classes.

    This means that the serialized fields of these domain classes need to be explicitly kept again in the ProGuard configuration so that they can be safely accessed through reflection.