12

I've been obfuscating my apps for a long while, with the following settings I took like mantras, because they were Google's recommendations

-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*

However, the other day I commented this line by mistake, the app got built correctly, and "apparently" works. I've made a lot of tests and couldn't made it crash.

So I wonder if those disabled optimization settings are needed ...

  • as of today's Android SDK and latest Proguard versions, I only target devices from Android 4.0.3 onwards (15), and use Proguard 5.1.
  • and for applications that don't do exotic stuff and have a properly written proguard.cfg instructing to keep the relevant problematic classes, etc.

Most answers here releated to this very issue have conflicting information, and are related to pretty old API versions.

One by one:

!code/simplification/arithmetic

I found a discussion on Google Groups where they say that simplification/arithmethic is not needed for SDK's after Android Donut. I assume then, I can safely enable this optimization.

!class/merging/*

It looks like proguard makes a good job in my projects with this optimization turned on:

[proguard]   Number of vertically merged classes:         296
[proguard]   Number of horizontally merged classes:       445

Are there other side effects besides the stack traces being incorrect? I mean, side effects related to the application crashing rather than to debug issues. I found this related question but it doesn't conclude wether it is safe or not.

!field/* and !code/simplification/cast

I read in this question answered by ProGuard's author that those were included to avoid bugs with older Proguard versions. So is it safe to activate them on Proguard 5.1?

Community
  • 1
  • 1
rupps
  • 9,712
  • 4
  • 55
  • 95
  • I also found flattening the the package structure, which places all the classes under one package -repackageclasses worked fine for me. Do you know it's possible to only allow vertical merging on a specific hierarchy of packages – pt123 Apr 29 '15 at 23:51
  • No answer. It is really strange. I've been wondering the same for a time. Did you find anything? Did you enable those optimization on production? – tasomaniac Jul 19 '15 at 17:16
  • Yes I enabled them successfully. Specifically, Class Merging does a nice job combined with 5 or more optimization passes. – rupps Jul 28 '15 at 12:20
  • 2
    Note that `class/merging/horizontal` may cause VerifyError if you have any `-dontwarn`, since that reference may be merged into your class. – kennytm Aug 07 '15 at 22:54
  • good to know! You mean a VerifyError fatal exception? or another warning? – rupps Aug 10 '15 at 12:10
  • 2
    The issue, raised by @kennytm, can be worked around by using `-keep,allowshrinking,allowobfuscation @android.annotation.TargetApi class *` (e.g. disable global optimizations for classes, not present in some of targeted versions). Naturally, to make that rule work, all such classes need to be annotated with `@TargetApi`. – user1643723 Aug 28 '17 at 04:20

2 Answers2

3

General advice: there's no guarantee that optimizations won't work, but there's always a risk. What the default Android proguard settings are attempting to do is provide a configuration that minimizes that risk, hence why they appear so conservative for your specific situation.

Enabling those optimizations just means that if something crashes, you can't be as certain as to the root cause. In general, the proguard step has less strong guarantees about what the outputs should be relative to the inputs, which is a source of non-determinism in your program. Small changes in code can result in significantly different changes in runtime behaviour, and it's not possible to know until you actually run the program, depending on your config.

In summary, if you can run your APK, and it all works - then great, the optimizations work for you. But, they're not guaranteed to.

Fabian Tamp
  • 4,416
  • 2
  • 26
  • 42
2

So is it safe to activate them on Proguard [5.1]?

It's a high risk move and I can give you an example where it causes a problem.

We're using ProGuard 5.2.1 and we're hitting a bug when reenabling the field/* optimization (more specifically, field/removal/writeonly seems to be causing the problem). Our code uses protobuf and enabling that optimization causes ProGuard to fail with this message on the third pass of optimizations:

Optimizing...
 Unexpected error while evaluating instruction:
  Class       = [com/google/protobuf/FieldSet$1]
  Method      = [()V]
  Instruction = [308] isub
  Exception   = [java.lang.IllegalArgumentException] (Value "com/google/protobuf/WireFormat$JavaType!" is not an integer value [proguard.evaluation.value.TypedReferenceValue])
Unexpected error while performing partial evaluation:
  Class       = [com/google/protobuf/FieldSet$1]
  Method      = [()V]
  Exception   = [java.lang.IllegalArgumentException] (Value "com/google/protobuf/WireFormat$JavaType!" is not an integer value [proguard.evaluation.value.TypedReferenceValue])
Warning: Exception while processing task java.io.IOException: java.lang.IllegalArgumentException: Value "com/google/protobuf/WireFormat$JavaType!" is not an integer value [proguard.evaluation.value.TypedReferenceValue]

This is to say that the fact that these optimizations have been disabled for so many years means that they probably haven't been as well maintained as others. Luckily this was caught at compile time but re-enabling some of these optimizations (e.g. horizontally merging classes via class/merging/*) might easily break your app in certain versions/builds of Android without being properly reported back to you "the developer" (e.g. it might crash dexopts or fail to install altogether with VerifyError).

Mike Laren
  • 8,028
  • 17
  • 51
  • 70
  • Re protobuf: this should be fixed in https://github.com/protocolbuffers/protobuf/pull/5734#event-2153856456 (This answer specifically pointed out the problematic optimization, which hinted at the fix, so - thanks!) – user1071136 Feb 21 '19 at 05:52