ProGuard是一款免费的Java类文件压缩器、优化器和混淆器。它能发现并删除无用类、字段(field)、方法和属性值(attribute)。它也能优化字节码并删除无用的指令。最后,它使用简单无意义的名字来重命名你的类名、字段名和方法名。经过以上操作的jar文件会变得更小,并很难进行逆向工程。这里提到了ProGuard的主要功能是压缩、优化和混淆,下面我就先介绍一下这些概念,然后再介绍ProGuard的基本使用方法。
        Java源代码(.java文件)通常被编译为字节码(.class文件)。而完整的程序或程序库通常被压缩和发布成Java文档(.jar文件)。字节码比Java源文件更简洁,但是它仍然包含大量的无用代码,尤其它是一个程序库的时候。ProGuard的压缩程序操作能分析字节码,并删除无用的类、字段和方法。程序只保留功能上的等价,包括异常堆栈描述所需要的信息。


通常情况下,编译后的字节码仍然包含了大量的调试信息:源文件名,行号,字段名,方法名,参数名,变量名等等。这些信息使得它很容易被反编译和通过逆向工程获得完整的程序。有时,这是令人厌恶的。例如像ProGuard这样的混淆器就能删除这些调试信息,并用无意义的字符序列来替换所有名字,使得它很难进行逆向工程,它进一步免费的精简代码。除了异常堆栈信息所需要的类名,方法名和行号外,程序只会保留功能上的等价。通过以上的了解,你应该明白为什么需要混淆了。


除了在压缩操作删除的无用类,字段和方法外,ProGuard也能在字节码级提供性能优化,内部方法有:

2、 删除不必要的字段存取

4、删除不必要的分支

6、删除未使用的代码

8、删除未使用的方法参数

10、在可能的情况下为类添加static和final修饰符

12、在可能的情况下使get/set方法成为内联的

14、选择性的删除日志代码

仍有一些明显需要优化的技术不被支持:

2。像get/set方法一样使其他方法成为内联


        ProGuard是一个命令行工具,并提供了图形化用户界面,它也可以结合Ant或J2ME Wireless Toolkit使用。通过ProGuard得到的更精简的jar文件意味着只需要更小的存储空间;网络传输更省时;装载速度更快和占用更小的内存空间。另 外,ProGuard非常快速和高效,它仅仅只花费几秒钟和几兆的内存在处理程序。它处理的顺序是先压缩,然后优化,最后才进行混淆。The results section presents actual figures for a number of applications.与其他Java混淆器相比,ProGuard的主要优势可能是它的基于模版文件的简单配置。一些直观的命令行选项或一个简单的 配置文件已经足够了。


Options

@filename

Short for '-include filename'.

-include filename

Read configuration options from the given file.

-basedirectory directoryname

Specifies the base directory for subsequent relative file names.

-injars class_path

Specifies the program jars (or wars, ears, zips, or directories).

-outjars class_path

Specifies the name of the output jars (or wars, ears, zips, or directories).

-libraryjars class_path

Specifies the library jars (or wars, ears, zips, or directories).

-dontskipnonpubliclibraryclasses

Don't ignore non-public library classes.

-dontskipnonpubliclibraryclassmembers

Don't ignore package visible library class members.

-keep class_specification

Preserve the specified classes and class members.

-keepclassmembers class_specification

Preserve the specified class members, if their classes are preserved as well.

-keepclasseswithmembers class_specification

Preserve the specified classes and class members, if all of the specified class members are present.

-keepnames class_specification

Preserve the names of the specified classes and class members (if they aren't removed in the shrinking step).

-keepclassmembernames class_specification

Preserve the names of the specified class members (if they aren't removed in the shrinking step).

-keepclasseswithmembernames class_specification

Preserve the names of the specified classes and class members, if all of the specified class members are present (after the shrinking step).

-printseeds [filename]

List classes and class members matched by the various -keep options, to the standard output or to the given file.

-dontshrink

Don't shrink the input class files.

-printusage [filename]

List dead code of the input class files, to the standard output or to the given file.

-whyareyoukeeping class_specification

Print details on why the given classes and class members are being kept in the shrinking step.

-dontoptimize

Don't optimize the input class files.

-assumenosideeffects class_specification

Assume that the specified methods don't have any side effects, while optimizing.

-allowaccessmodification

Allow the access modifiers of classes and class members to be modified, while optimizing.

-dontobfuscate

Don't obfuscate the input class files.

-printmapping [filename]

Print the mapping from old names to new names for classes and class members that have been renamed, to the standard output or to the given file.

-applymapping filename

Reuse the given mapping, for incremental obfuscation.

-obfuscationdictionary filename

Use the words in the given text file as obfuscated method names.

-overloadaggressively

Apply aggressive overloading while obfuscating.

-useuniqueclassmembernames

Ensure uniform obfuscated class member names for subsequent incremental obfuscation.

-defaultpackage [package_name]

Repackage all class files that are renamed into the single given package.

-dontusemixedcaseclassnames

Don't generate mixed-case class names while obfuscating.

-keepattributes [attribute_name,...]

Preserve the given optional attributes; typically LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.

-renamesourcefileattribute [string]

Put the given constant string in the SourceFile attributes.

-verbose

Write out some more information during processing.

-dontnote

Don't print notes about class casts of variable dynamically created objects.

-dontwarn

Don't warn about unresolved references at all.

-ignorewarnings

Print warnings about unresolved references, but continue processing anyhow.

-dump [filename]

Write out the internal structure of the processed class files, to the standard output or to the given file.

Notes:

  • class_path is a list of jars, wars, ears, zips, and directories, with optional filters, separated by path separators.
  • filename can contain Java system properties delimited by '<' and '>'.
  • If filename contains special characters, the entire name should be quoted with single or double quotes.

Overview of Keep Options

Keep

From being removed or renamed

From being renamed

Classes and class members

-keep

-keepnames

Class members only

-keepclassmembers

-keepclassmembernames

Classes and class members, if class members present

-keepclasseswithmembers

-keepclasseswithmembernames

Class Specifications


[[!]public|final|abstract ...] ([!]interface)|class classname
    [extends|implements classname]
[{
    [[!]public|private|protected|static|volatile|transient ...] <fields> |
                                                                      (fieldtype fieldname);
    [[!]public|private|protected|static|synchronized|native|abstract|strictfp ...] <methods> |
<init>(argumenttype,...) |
classname(argumenttype,...) |
                                                                                           (returntype methodname(argumenttype,...));
    [[!]public|private|protected|static ... ] *;
    ...
}]


Notes:

  • Class names must always be fully qualified, i.e. including their package names.
  • Types in classname, returntype, and argumenttype can contain wildcards: '?' for a single character, '*' for any number of characters (but not the package separator), '**' for any number of (any) characters, and '%' for any primitive type.
  • fieldname and methodname can contain wildcards as well: '?' for a single character and '*' for any number of characters.