简介

切入点(Entry Points)

ProGuard 是一个能对 Java 代码进行压缩(Shrink)、优化(Optimize)、混淆(Obfuscate)和预校验(Pre-verify)的工具。切入点用于定义代码是否需要被保留、丢弃或混淆,通常为含有主方法或主要应用组件的类。

  • 压缩(Shrink):从切入点开始递归地判断哪些类或类成员被使用,所有其他未被使用类(Class)、字段(Field)、方法(Method)和属性(Attribute)将会被移除。
  • 优化(Optimize):进一步在字节码层面优化代码,在优化过程中,可以将非切入点的类和方法设置为 staticprivatefinal 。同时可以移除未使用的参数,并且内联一些方法。
  • 混淆(Obfuscate):将会使用无意义的简短名称重命名非切入点的类及类成员,但会确保切入点仍然可以通过原始名称访问到它们,这使代码库更小、更有效,并且更难进行反向工程。
  • 预校验(Preveirfy):预验证步骤不需要指定切入点,将会把预验证信息添加到类中。

反射(Reflection)

动态创建或调用的类或类成员必须被指定为切入点。对于这些类和类成员,通常不可能准确的得知哪些需要被保留,因为其名称可能从配置文件中读取。因此,需要在 ProGuard 的配置文件中使用 -keep 参数指定保留这些类或类成员。而对于一些不显现的反射,配置文件中的 -addconfigurationdebug 选项允许 ProGuard 使用调试语句检测处理过的代码,而通过打印的日志,可灵活的调整 ProGuard 的配置,以免需要被保留的类或类成员被移除或混淆。

使用

配置文件

基本语法

Proguard 配置文件提供单行注释,从 # 字符开始,一直到行尾结束。单词和分隔符之间的额外空格将被忽略。带有空格或特殊字符的文件名应该用单引号或双引号括起来。

通用选项

  • -verbose :指定在处理过程中的日志级别。如果程序以异常终止,该选项将打印出整个堆栈跟踪,而不仅仅是异常消息。
  • -dontwarn [class_filter] :使用一个正则过滤器指定不对未解决的引用和其他重要问题输出警告日志。

输入及输出配置(Input / Output options)

  • -include <filename> :递归地从给定的文件中读取配置选项,可被缩写为 @filename ,可接受绝对路径和相对路径,相对路径遵循以下规则:

    • 如果基本目录被指定,则相对于项目的基本目录。
    • 如果配置文件的目录被指定,则相对于配置文件的所在的目录。
    • 前二者未被指定时,相对于当前的工作目录。
  • -basedirectory <directoryname> :指定配置参数或配置文件中所有后续相对文件的基本目录。

  • -injars <class_path> :指定需要被处理的输入 jars,其中的类文件将被处理并写入输出 jars。默认情况下,任何非类文件都将被复制而不被更改。

  • -outjars <class_pat> :指定输出 jars 的名称,在 -injars 中指定处理的输入 jars将被写到指定的输出 jar。这意味着可以将输入和输出以组的形式对应起来。

保留选项(Keep options)

  • -keep [modifier] <class_specification> :指定类或类成员为切入点。
  • -keepclassmembers [modifier] <class_specification> :指定类成员为切入点。
  • -keepclasseswithmembers [modifier] <class_specification> :指定类和类成员为切入点。

压缩选项(Shrinking options)

  • -dontshrink :指定不压损输入类文件。默认情况下,除了各种 -keep 选项列出的类和类成员以及它们直接或间接依赖的类和类成员会被保留以外,所有其他的类和类成员都被移除。在压缩步骤之后的优化步骤同时也可能会移除一些类或类成员。
  • -printusage [filename] :输出指定类文件中不被使用的代码。
  • -whyareyoukeeping <class_specification> :输出指定的类和类成员在压缩步骤中被保留的原因,如果指定了 -verbose 选项,输出将包含完整的字段和方法签名。

优化选项(Optimization options)

  • -dontoptimize :指定不优化输入类文件。默认情况下,所有方法将会在字节码级别进行优化。
  • -optimizationpasses <n> :指定要执行的优化传递的次数。默认情况下,只执行一次传递。多次传递可能会导致进一步的改进。如果优化通过后没有发现任何改进,则优化结束。

混淆选项(Obfuscation options)

  • -dontobfuscate :指定不混淆输入类文件。默认情况下,除了作为切入点的类和类成员,其余的类和类成员的名称将会被新的短随机名称替代。同时用于调试的内部属性也将被移除。
  • -printmapping [filename] :指定为已被重命名的类和类成员打印从旧名称到新名称的映射,映射关系可被打印到文件或日志当中。
  • -applymapping <filename> :指定使用给定的映射文件进行混淆。映射文件中列出的类和类成员将接收与其指定的名称,未被提及的类和类成员将接收新名称。这个选项对于增量混淆非常有用,例如处理对现有代码块的附加组件或小补丁。如果代码的结构发生了根本性的变化,ProGuard 可能会打印出应用映射会导致冲突的警告。
  • -obfuscationdictionary <filename> :指定一个文本文件,从该文件中使用所有有效单词作为混淆字段和方法名称。默认情况下,将会使用短名称如 ab 等用作混淆后的名称。
  • -keepattributes [attribute_filter] :指定要保留的任何可选属性。属性可以用一个或多个 -keepattributes 选项指定。可选过滤器是一个逗号分隔的属性名列表,属性名可以包含 ?*** 通配符,并且可以包含 ! 用于取反。

预校验选项(Pre-verification options)

  • -dontpreverify :指定不预先验证已处理的类文件。默认情况下,类文件将会在作用在 JME 或 Java 6 及其以上的版本时执行预校验。对于 JME,预验证是必须的,因此如果指定此选项,则需要对处理后的代码运行外部预验证器。对于 Java 6,预验证是可选的,但是对于 Java 7,它是必需的。只有当作用于 Android 平台时,预校验是没有必要的,所以可以选择关闭它来减少一些处理时间。
  • -android :指定处理后的类文件作用于 Android 平台,ProGuard 会确保一些功能与 Android 相兼容。

过滤器

字符 匹配规则 示例
* 匹配多个字符,不包括包分隔符 . 和目录分隔符 \ com.example.*com.example.Test
** 匹配多个字符,可以包含包分隔符 . 和目录分隔符 \ com.*com.example.Test
<n> 匹配在同一选项中第 n 个通配符 com.example.*es<1>com.example.Test