Android ProGuard:最具侵略性的优化

lf2*_*215 61 optimization android proguard

Android的官方proguard文档显示了两个主要的优化:

  • 设置minifyEnabledtrue
  • proguard-android-optimize.txt 而不是proguard-android.txt

这两个是最具侵略性的可能设置吗?

我正在编写一个android库,需要确保人们使用我的库时我的代码不会破坏.(我知道我可以在我的库中放置规则来对抗使用该库的应用程序上设置的proguard配置,但如果我不需要,我不想这样做.)

And*_*ICE 54

请记住,最好的ProGuard配置 - 是一个具有最少例外的配置.根据我理解的例外情况:

 -keepclassmembers class * extends android.content.Context {
    public void *(android.view.View);
    public void *(android.view.MenuItem);
 }
Run Code Online (Sandbox Code Playgroud)

让我们来看看proguard-android-optimize.txt并查看优化/混淆选项.

有关ProGuard选项的详细说明,请使用选项

-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/* - 可能的优化列表,!意味着否定,所以不使用此优化

-optimizationpasses 5 指定要执行的优化传递的数量.默认情况下,执行单次传递.多次通过可能会导致进一步的改进.如果在优化过程后未找到任何改进,则优化结束.仅适用于优化时.
用法:好的,看起来默认的5次传递就足够了

-allowaccessmodification 指定在处理期间可以扩展类和类成员的访问修饰符.这可以改善优化步骤的结果.
用法:好的,是的,看起来像改进优化

-dontpreverify 在定位Android时,不需要预先验证,因此请不要将其关闭以减少处理时间.但是这个选项对代码的不可破坏性没有影响.
用法:好的,只需稍微减少处理时间

-dontusemixedcaseclassnames 指定在混淆时不生成混合大小写的类名.默认情况下,混淆的类名称可以包含大写字符和小写字符的混合.这创造了完全可接受和可用的罐子.
用法:问题,我找不到为什么添加这个选项的确切原因,但看起来更改类名abcdef从而AbSdEf不会使代码牢不可破

-dontskipnonpubliclibraryclasses 指定不忽略非公共库类.从版本4.5开始,这是默认设置.
用法:好的,非常实用

proguard-android-optimize.txt中不包含以下选项:

-mergeinterfacesaggressively 指定可以合并接口,即使它们的实现类没有实现所有接口方法...设置此选项会降低某些JVM上处理代码的性能
用法:BAD,对Android来说看起来很危险,不包括在内配置,禁止类/合并/优化的总和

-overloadaggressively 指定在混淆时应用积极的重载.然后,多个字段和方法可以获得相同的名称,只要它们的参数和返回类型不同,这是Java字节码所要求的(不仅仅是它们的参数,如Java语言所要求的)
用法:BAD,谷歌的Dalvik VM不能处理重载的静态字段.

-repackageclasses '' 指定通过将所有重命名的类文件移动到单个给定包中来重新打包它们.如果没有参数或空字符串(''),则会完全删除包.此选项会覆盖-flattenpackagehierarchy选项.
用法:好的,谷歌使用,所以看起来我们至少找到了我们可以添加到配置中的选项

所以我知道只有一个对于混淆和非危险选项更有用:
-repackageclasses ''

另请注意解码堆栈跟踪.ProGuard还会从堆栈跟踪中删除文件名和行号.这使得发现错误非常复杂.您可以通过在配置中添加以下代码来保留行号:

-renamesourcefileattribute SourceFile 
-keepattributes SourceFile,LineNumberTable
Run Code Online (Sandbox Code Playgroud)

这将保留行号,但用"SourceFile"替换stacktrace中的文件名.

另外不要忘记ProGuard看起来很脆弱,因为它不会加密字符串资源,因此请考虑使用DexGuard或加密重要字符串(如标记,网址)本身.


Mil*_*ský 7

根据优化文件的评论,优化会带来一定的风险,如果使用,必须彻底测试应用程序.根据我的经验,有必要禁用代码/简化/高级,因为它导致在lambda外部初始化的最终局部变量在lambda内为NULL.调试和查找非常困难.因此我的优化设置如下:

-optimizations!code/simplifiedification/cast,!code/simplifiedification/advanced,!field/*,!class/merge/*,!method/removal/parameter,!method/propagation/parameter

请注意,如果您定位Android 2.0及更低版本(这是非常不可能的),也必须禁用代码/简化/算术.除此之外,我还必须禁用方法/删除/参数和方法/传播/参数,因为这些隐式启用代码/简化/高级(有关详细信息,请参阅ProGuard手册).