ProGuard是一个Java Class文件的Shrinker,optimizer,obfuscator以及Preverifier。
这些步骤主要是为了让代码变得更精简,更高效,变得对逆向更难。而最后一个步骤:preverification,该步骤会在classes中添加预验证信息,而预验证的信息是在Java 6以上的版本所需要的。
这几个步骤每一个都是可选的,例如,ProGuard可以用来列出Dead Code,也可以在Java6中更高效的预验证class文件。

ProGuard
ProGuard只读取jars,wars,zips,ears等文件格式的文件。然后对它们进行shrinks,optimizes,obfuscates,preverifies。也可以传入多个文件,它们会一个一个被Shrink。ProGuard会把处理的结果写到一个或者多个Jar包中。如果输入的文件包含了资源文件,那么它们的名字和内容都会被obfuscated类名所影响。
ProGuard会指定Library Jar作为输入,而这些输入文件也是我们需要编译代码所需要的。ProGaurd使用它们来重建正确处理所需的类依赖关系,Library它们本身会保持不变,你可以把他们放到最终应用的Class Path中。
为了决定哪些代码应该被保留,而哪些代码应该被丢弃或者混淆的,你可以指定一个或者多个代码入口。这些入口可以是有main函数的class文件等等。
递归决定哪些classes以及class members会需要用到。而其他的classes和class members就会被丢弃private,static,final,而没用的参数也会被移除,一些函数会被内联反射和自检(introspection)是代码自动处理中特殊的问题。
在ProGuard中,Classes和Class Member都可以创建或者通过名字动态调用,这种方式也是一个特殊的入口。
例如,
Class.forName()可能会在Runtime引用很多的Class。而这种方式的类,我们无法预见哪些类必须使用原始名称来保留,例如Class的名称是从配置文件中读取的。
因此,我们需要在ProGuard的配置文件中进行配置。而最简单的配置则是通过-keep选项。然而,ProGuard已经检测并且处理了以下这些Case:
被引用的Class和Class Member会在Shrinking阶段被保存,并且String参数也会在Obfuscating阶段正确的更新
更多的,ProGuard对于Keep一些必须出现的Class或者Class Members有一些建议:
例如,ProGuard会关注到(SomeClass)Class.forName(variable).newInstance()。这种我们需要指定类或者SomeClass接口、实现类应该被保留。
混淆很多反射的代码需要反复测试,尤其是不需要内部构建的代码。
如果想要执行ProGuard,只需:
java -jar proguard.jar options ...你可以在ProGuard安装的lib目录下找到proguard的Jar包。或者,把bin目录包含到命令行脚本中去。
一般我们都会把大多数的Options添加到一个配置文件中,如myconfig.pro,然后调用:
java -jar proguard.jar @myconfig.pro你也可以在命令行参数后再添加其他的参数,例如:
java -jar proguard.jar @myconfig.pro -verbose在配置文件中,我们可以通过##字符来进行注释。例如:
##This is Comment##
如果特殊的文件名带有空格,则需要使用单引号或者双引号。
Options可以通过命令行参数以及配置文件中任意组合。也就意味着,你可以引用任意的命令行参数,来避免Shell被特殊的字符扩张。
Options的顺序是无关的。