Android ProGuard:最激进的优化
Android的官方proguard文档显示了两个主要的优化:
- 将
minifyEnabled
设置为true
- 使用
proguard-android-optimize.txt
代替proguard-android.txt
这两个最积极的可能设置?
我正在编写一个Android库,并且需要确保何时人们使用我的库,我的代码不会中断。 (我知道有些规则可以放在我的库中,用来对付使用该库的应用程序中设置的proguardconfiguration,但是如果不需要,我不想这样做)。
请记住,最好的ProGuardconfiguration – 是一个极less有例外的configuration。 根据例外,我明白:
-keepclassmembers class * extends android.content.Context { public void *(android.view.View); public void *(android.view.MenuItem); }
让我们通过proguard-android-optimize.txt来查看优化/混淆选项。
有关ProGuard选项的详细说明,请使用此选项
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
这个 – 可能的优化列表! 意味着否定,所以这个优化不被使用
-optimizationpasses 5
指定要执行的优化传递的数量。 默认情况下,执行一次传递。 多次传递可能会导致进一步的改进。 如果在优化后没有find改进,则优化结束。 只适用于优化。
用法: 好的 ,看起来像默认的5遍就足够了
-allowaccessmodification
指定在处理期间可以扩展类和类成员的访问修饰符。 这可以改善优化步骤的结果。
用法: 好的 ,是的,看起来像提高优化
-dontpreverify
当瞄准Android时,preverifing是不必要的,所以dontpreverify把它closures以减less处理时间。 但是这个选项不影响代码的不可破解性。
用法: 好吧 ,稍微减less处理时间
-dontusemixedcaseclassnames
指定在模糊处理时不生成混合大小写的类名称。 默认情况下,混淆的类名可以包含大写字母和小写字符的混合。 这创造完全可接受和可用的jar子。
用法: QUESTIONABLE ,找不到确切的原因为什么添加这个选项,但是看起来像从abcdef
到AbSdEf
更改类名不会使代码AbSdEf
破解
-dontskipnonpubliclibraryclasses
指定不忽略非公共库类。 从版本4.5开始,这是默认设置。
用法: 好的 ,非常有用
以下选项不包含在proguard-android-optimize.txt中:
-mergeinterfacesaggressively
指定可以合并接口,即使它们的实现类不实现所有接口方法…设置此选项可能会降低某些JVM上处理的代码的性能
用法: BAD ,对Android来说看起来很危险,不包括在configuration中,禁止类/合并/优化中的总和
-overloadaggressively
指定在混淆时应用主动重载。 只要它们的参数和返回types不同,多个字段和方法就可以获得相同的名称,正如Java字节码所要求的那样(不仅仅是它们的参数,正如Java语言所要求的那样)
用法: BAD ,Google的Dalvik虚拟机无法处理重载的静态字段。
-repackageclasses ''
指定将所有重命名的类文件重新打包,将它们移动到给定的单个包中。 没有参数或空string(''),包被完全删除。 该选项将覆盖-flattenpackagehierarchy选项。
用法: 好的 ,由Google使用,所以看起来我们至less已经find了我们可以添加到我们的configuration的选项
所以我知道只有一个更有用的混淆和非危险的选项:
-repackageclasses ''
另外请注意解码堆栈跟踪。 ProGuard也从堆栈中删除文件名和行号。 这使得发现错误非常复杂。 您可以通过将以下代码添加到您的configuration中来保留行号:
-renamesourcefileattribute SourceFile -keepattributes SourceFile,LineNumberTable
这将保留行号,但用“SourceFile”replace堆栈跟踪中的文件名。
另外不要忘记,ProGuard看起来很脆弱,因为它不会encryptionstring资源 ,所以考虑使用DexGuard或者自己encryption重要的string(如标记,url)。
根据优化文件的评论,优化会带来一定的风险,如果使用,应用程序必须彻底testing。 根据我的经验,有必要禁用代码/简化/高级,因为它导致最终的局部variables在lambda之外被初始化为lambda中的空值。 debugging和查找非常困难。 所以我的优化设置如下:
代码/简化/高级,!字段/ *,!类/合并/ *,!方法/删除/参数,!方法/传播/参数
请注意,如果您的目标是Android 2.0或更低(这是不太可能的),代码/简化/算术也必须被禁用。 除此之外,我还必须禁用方法/删除/参数和方法/传播/参数,因为这些隐式启用代码/简化/高级(更多信息参见ProGuard手册 )。