Android ProGuard:最具侵略性的优化

时间:2016-02-10 17:17:48

标签: android optimization proguard

Android官方proguard documentation显示了两项主要优化:

  • minifyEnabled设为true
  • 使用proguard-android-optimize.txt 而不是proguard-android.txt

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

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

3 个答案:

答案 0 :(得分:49)

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

 -keepclassmembers class * extends android.content.Context {
    public void *(android.view.View);
    public void *(android.view.MenuItem);
 }

让我们一起浏览proguard-android-optimize.txt并查看优化/混淆选项。

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

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

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

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

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

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

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

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

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

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

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

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

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

-renamesourcefileattribute SourceFile 
-keepattributes SourceFile,LineNumberTable

这将保留行号,但用#34; SourceFile"替换堆栈跟踪中的文件名。

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

答案 1 :(得分:7)

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

  

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

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

答案 2 :(得分:1)

在libminecraft 1.15.2零版中,这是第一个使用新的libminecraft先进技术的全程序优化的Minecraft版本,我仅使用gson,内联和代码优化。这样做是为了减轻使用完全优化可能带来的不稳定影响。

现在我们有了Minecraft 1.16.2和ProGuard 7.0.0,我使用了完全优化而没有任何稳定性问题(我实际上将ProGuard与Allatori堆叠在一起,但仍然没有遇到稳定性问题,因为Allatori的控制和数据流优化比ProGuard)。

我在libminecraft 1.16.2中运行了3次ProGuard。一次仅执行5次代码优化,一次进行所有非代码优化,一次仅进行2次代码优化。另外,我将Allatori用于优化的最后一步,因为它执行了非常高质量的控制和数据流优化。