ProGuard Usage 翻译



Usage  用法

To run ProGuard, just type:

运行ProGuard,只需输入:

java -jar proguard.jar options ...

You can find the ProGuard jar in the lib directory of the ProGuard distribution. Alternatively, the bin directory contains some short Linux and Windows scripts containing this command. Typically, you'll put most options in a configuration file (say, myconfig.pro), and just call:


你可以在ProGuard lib目录中找到 ProGuard jar。一些包含此命令的LInux和Windows 短脚本可在bin 目录中找到供你选择。典型的用法是,你将大多数的参数选项写入一个配置文件中(如,myconfig.pro),然后运行:


java -jar proguard.jar @myconfig.pro

You can combine command line options and options from configuration files. For instance:


你可以将命令行选项和配置文件选项结合使用。举个栗子:


java -jar proguard.jar @myconfig.pro -verbose

You can add comments in a configuration file, starting with a # character and continuing until the end of the line.

你可以在配置文件添加注释,用法是以#开头,接在#后面的单行都是注释。


Extra whitespace between words and delimiters is ignored. File names with spaces or special characters should be quoted with single or double quotes.


文字和分隔符中间的空格是被忽略的。包含空格或者特殊字符的文件名需要用单引号或者双引号引用。


Options can be grouped arbitrarily in arguments on the command line and in lines in configuration files. This means that you can quote arbitrary sections of command line options, to avoid shell expansion of special characters, for instance.


命令行选项可以在命令行和配置文件中任意组合。这就意味着你可以引用任意命令行选项,而避免设计特殊的shell特殊语句扩展。


The order of the options is generally irrelevant. For quick experiments, you can abbreviate them to their first unique characters.


选项的顺序通常是无关紧要的。为了快速的执行,你可以缩写他们,用他们的第一个特殊字符标示他们。


The sections below provide more details:


以下的单元组提供更多详细信息:



Input/Output Options

@filename

Short for '-include filename'.    '-include filename'的简写

-include filename  

Recursively reads configuration options from the given file filename.  


从给定的文件中递归的读取配置选项。 (如:-include lib/annotations.pro)


-basedirectory directoryname

Specifies the base directory for all subsequent relative file names in these configuration arguments or this configuration file.


指定配置参数中或配置文件中所有有关联的文件的基础目录。


-injars class_path

Specifies the input jars (or aars, wars, ears, zips, apks, or directories) of the application to be processed. The class files in these jars will be processed and written to the output jars. By default, any non-class files will be copied without changes. Please be aware of any temporary files (e.g. created by IDEs), especially if you are reading your input files straight from directories. The entries in the class path can be filtered, as explained in the filters section. For better readability, class path entries can be specified using multiple -injars options.


指定应用中需要proguard处理的jars(或 aars,wars,ears,zips,asks等文件或目录)。这些jars中的class文件将被proguard处理并被写入output jars中。默认情况下,任何非class文件将被原封不动的拷贝一份。请留意处理那些临时的文件(如 IDEs工具创建的配置文件等),尤其是当你直接指定目录的时候。这些class path入口可设置过滤器,过滤器内容可查看过滤器单元。为了便于阅读,class path入口可以通过重复的使用-injars选项进行指定。


-outjars class_path

Specifies the names of the output jars (or aars, wars, ears, zips, apks, or directories). The processed input of the preceding -injars options will be written to the named jars. This allows you to collect the contents of groups of input jars into corresponding groups of output jars. In addition, the output entries can be filtered, as explained in the filters section. Each processed class file or resource file is then written to the first output entry with a matching filter, within the group of output jars.


指定输出的jars(或 aars,wars,ears,zips,asks等文件或目录)的文件名称。之前在-injars选项中指定的被处理后的内容将写入outjars 指定的文件中。它允许你以组形式收集的jars内容按照组形式输出为对应的outjars组里。此外,output通道可以设置过滤器,过滤器详情查看过滤器单元。每一个处理的class文件或者resource文件会写入在output jars组中与过滤器匹配的第一个output通道。


-injars base_in1.jar

-injars base_in2.jar

-injars base_in3.jar

-outjars base_out.jar


-injars  extra_in.jar

-outjars extra_out.jar



You must avoid letting the output files overwrite any input files. For better readability, class path entries can be specified using multiple -outjars options. Without any -outjars options, no jars will be written.


你需要避免让输出文件覆盖了输入文件。为了便于阅读,class path出口可以通过重复的使用-outjars选项进行指定。如果没有任何-outjars选项,则不会输出任何文件。



-libraryjars class_path

Specifies the library jars (or aars, wars, ears, zips, apks, or directories) of the application to be processed. The files in these jars will not be included in the output jars. The specified library jars should at least contain the class files that are extended by application class files. Library class files that are only called needn't be present, although their presence can improve the results of the optimization step. The entries in the class path can be filtered, as explained in the filters section. For better readability, class path entries can be specified using multiple -libraryjars options.

Please note that the boot path and the class path set for running ProGuard are not considered when looking for library classes. This means that you explicitly have to specify the run-time jar that your code will use. Although this may seem cumbersome, it allows you to process applications targeted at different run-time environments. For example, you can process J2SE applications as well as JME midlets or Android apps, just by specifying the appropriate run-time jar.


指定应用中需要处理的library jars (or aars, wars, ears, zips, apks, or directories)。在library jars中的文件不会被写入output jars中。指定的library jars应该至少包含应用class文件中需要继承的class。

Library class 文件只需要被引用而不需要存在,虽然他们的存在可以提高优化的结果。class path的入口可以设置过滤器,详见过滤器单元。为了便于阅读,class path出口可以通过重复的使用-libraryjars选项进行指定。

请注意,proguard执行时的运行时jar包环境是未知的。这就意味着,你需要明确指定运行时jar包,你的代码才能使用。虽然看起来比较繁琐,但它能允许你处理针对不同的运行环境的应用。举个栗子,你可以处理J2SE应用,JME应用和Android应用。只要指定预处理应用对应的运行时jar包就好了。


-skipnonpubliclibraryclasses

Specifies to skip non-public classes while reading library jars, to speed up processing and reduce memory usage of ProGuard. By default, ProGuard reads non-public and public library classes alike. However, non-public classes are often not relevant, if they don't affect the actual program code in the input jars. Ignoring them then speeds up ProGuard, without affecting the output. Unfortunately, some libraries, including recent JSE run-time libraries, contain non-public library classes that are extended by public library classes. You then can't use this option. ProGuard will print out warnings if it can't find classes due to this option being set.


指定在读取library jars时跳过读取那些non-public classes,以便于提高proguard的处理速度和减少内存消耗。默认情况下,proguard像public library classes一样读取 non-public classes。然而,如果他们不影响input jars里的现行代码,non-public classes经常是无关紧要的。忽略他们,提高proguard速度,也不影响output的输出。不幸的是,一些libraries,包括当前的 JSE run-time libraries,包含有被public library classes 继承的non-public library classes。你就不能使用这个选项了。proguard将会打印因为这个选项的设置而引起的 it can’t find classes警告。


-dontskipnonpubliclibraryclasses

Specifies not to ignore non-public library classes. As of version 4.5, this is the default setting.


不忽略non-public library classes.从4.5版本起,这个设置是默认的。


-dontskipnonpubliclibraryclassmembers

Specifies not to ignore package visible library class members (fields and methods). By default, ProGuard skips these class members while parsing library classes, as program classes will generally not refer to them. Sometimes however, program classes reside in the same packages as library classes, and they do refer to their package visible class members. In those cases, it can be useful to actually read the class members, in order to make sure the processed code remains consistent.


不忽略包级的library class里的成员(fields 和 methods)。默认的,当解析library classes时proguard会跳过这些类成员,因为代码类通常不引用他们。然而有时候,代码类与library classes处于用一个包名下,那就可以引用包级成员了。这样,-dontskipnonpubliclibraryclassmembers 在确实读取了这些包级成员时派上了用场,以确保处理后的代码可用性。



-keepdirectories [directory_filter]

Specifies the directories to be kept in the output jars (or aars, wars, ears, zips, apks, or directories). By default, directory entries are removed. This reduces the jar size, but it may break your program if the code tries to find them with constructs like "mypackage.MyClass.class.getResource("")". You'll then want to keep the directory corresponding to the package, "-keepdirectories mypackage". If the option is specified without a filter, all directories are kept. With a filter, only matching directories are kept. For instance, "-keepdirectories mydirectory" matches the specified directory, "-keepdirectories mydirectory/*" matches its immediate subdirectories, and "-keepdirectories mydirectory/**" matches all of its subdirectories.


指定目录结构被保留在output (or aars, wars, ears, zips, apks, or directories)jars中。默认情况,目录结构是被移除的。这样可以减少jar的大小,但如果你使用类似于"mypackage.MyClass.class.getResource(“”)结构的代码时,它将破坏你的程序。你若想保留对应的包名目录结构,使用"-keepdirectories mypackage”。如果选项没有设置过滤器,所有的目录将被保留。使用过滤器,只用匹配的目录将被保留。举个栗子,"-keepdirectories mydirectory" 只匹配mydirectory目录,"-keepdirectories mydirectory/*”匹配mydirectory的一层子目录,"-keepdirectories mydirectory/**则匹配mydirectory下所有目录。


-target version

Specifies the version number to be set in the processed class files. The version number can be one of 1.01.11.21.31.41.5 (or just 5), 1.6(or just 6), 1.7 (or just 7), or 1.8 (or just 8). By default, the version numbers of the class files are left unchanged. For example, you may want toupgrade class files to Java 6, by changing their version numbers and having them preverified. You probably shouldn't downgrade the version numbers of class files, since the code may contain constructs that are not supported in older versions.


指定处理后文件使用的java版本号。版本号形式可以是 1.01.11.21.31.41.5 (or just 5), 1.6(or just 6), 1.7 (or just 7), or 1.8 (or just 8). 默认的,class files的版本号是不会变化的。如果你想升级class files 到java6,可以改变这个版本号,使之进行预验证。你可能不能降低classes files的版本号,因为文件中可能会包含低版本不支持的结构。



-forceprocessing

Specifies to process the input, even if the output seems up to date. The up-to-dateness test is based on a comparison of the date stamps of the specified input, output, and configuration files or directories.


指定强行处理input数据,即使output的数据是最新的。验证数据是否是最新的判断是建立在指定的input,output,配置文件或目录的日期戳的比较上。




Keep Options  Keep选项

-keep [,modifier,...] class_specification

Specifies classes and class members (fields and methods) to be preserved as entry points to your code. For example, in order to keep an application, you can specify the main class along with its main method. In order to process a library, you should specify all publicly accessible elements.


指定你代码里的类和类成员(常变量和方法)保留原貌。举个栗子,为了保护一个应用,你可以指定main class的main 方法被保留。而当处理一个library,你应该保留所有的公共可用的元素。



-keepclassmembers [,modifier,...] class_specification

Specifies class members to be preserved, if their classes are preserved as well. For example, you may want to keep all serialization fields and methods of classes that implement the Serializable interface.


指定类成员被保留,如果他们的类也被保护(类没有被保护似乎也有效)。例如,你要保留所有实现Serializable接口的类的序列化成员。


-keepclassmembers class * implements java.io.Serializable {

    private static final java.io.ObjectStreamField[] serialPersistentFields;

    private void writeObject(java.io.ObjectOutputStream);

    private void readObject(java.io.ObjectInputStream);

    java.lang.Object writeReplace();

    java.lang.Object readResolve();

}



-keepclasseswithmembers [,modifier,...] class_specification

Specifies classes and class members to be preserved, on the condition that all of the specified class members are present. For example, you may want to keep all applications that have a main method, without having to list them explicitly.

指定在所有指定的类成员都存在的情况下,保护类和类成员。例如你要保存所有有main方法的应用,不用一一明确的指定每一个。


-keepclasseswithmembers public class * {

    public static void main(java.lang.String[]);

}



-keepnames class_specification

Short for -keep,allowshrinking class_specification

Specifies classes and class members whose names are to be preserved, if they aren't removed in the shrinking phase. For example, you may want to keep all class names of classes that implement the Serializable interface, so that the processed code remains compatible with any originally serialized classes. Classes that aren't used at all can still be removed. Only applicable when obfuscating.

 -keep,allowshrinking class_specification 的缩写

指定类和类成员名被保护,如果他们没有被缩减解析被删减掉。例如,你想保留所有实现了序列化接口的类名,以便处理后的代码仍然可以兼容原来的序列化类。那些没有使用的类依然会被删除。此选项只有在运行了混淆选项的时候有效。


-keepclassmembernames class_specification

Short for -keepclassmembers,allowshrinking class_specification

Specifies class members whose names are to be preserved, if they aren't removed in the shrinking phase. For example, you may want to preserve the name of the synthetic class$ methods when processing a library compiled by JDK 1.2 or older, so obfuscators can detect it again when processing an application that uses the processed library (although ProGuard itself doesn't need this). Only applicable when obfuscating.

 -keepclassmembers,allowshrinking class_specification 的缩写

指定类成员名被保护,如果他们没有被缩减解析删减掉。例如,你想保留用JDK1.2或者更老版本编译的library项目里的内部类方法,当处理一个使用了这个处理的library的应用的时候混淆器能再次发现他。此选项只有在运行了混淆选项的时候有效。 



-keepclasseswithmembernames class_specification

Short for -keepclasseswithmembers,allowshrinking class_specification

Specifies classes and class members whose names are to be preserved, on the condition that all of the specified class members are present after the shrinking phase. For example, you may want to keep all native method names and the names of their classes, so that the processed code can still link with the native library code. Native methods that aren't used at all can still be removed. If a class file is used, but none of its native methods are, its name will still be obfuscated. Only applicable when obfuscating.

 -keepclasseswithmembers,allowshrinking class_specification 的缩写

指定类和类成员被保护,前提是所有指定类成员在被缩减处理后依然存在。例如,你想保护所有的native方法名和他们的类名,使处理后的代码仍然可以联系到native library code.没有被使用的native方法依然会被删除。如果一个类有被使用,但它的native方法都没有被使用,那么它的类名仍然会被混淆。此选项只有在运行了混淆选项的时候有效。 


-printseeds [filename]

Specifies to exhaustively list classes and class members matched by the various -keep options. The list is printed to the standard output or to the given file. The list can be useful to verify if the intended class members are really found, especially if you're using wildcards. For example, you may want to list all the applications or all the applets that you are keeping.


罗列出一个被-keep相关选项匹配的类和类成员的详细列表。这个列表将被打印到output中或者指定的路径中。这个列表能被用于验证是否期望的类成员真的被保护到,尤其是当你使用通配符的时候。例如,你想列出所有应用中你想保护的。


Shrinking Options   缩减选项

-dontshrink

Specifies not to shrink the input class files. By default, shrinking is applied; all classes and class members are removed, except for the ones listed by the various -keep options, and the ones on which they depend, directly or indirectly. A shrinking step is also applied after each optimization step, since some optimizations may open the possibility to remove more classes and class members.


指定不缩减输入的class文件。缩减选项是默认执行的。除了被keep保护的,以及相互间有直接或间接依赖关系的类和类成员,其他的类和类成员都会被删除掉。缩减步骤会在每次优化后再执行一次,因为一些优化后可能存在符合删除条件的类和类成员。



-printusage [filename]

Specifies to list dead code of the input class files. The list is printed to the standard output or to the given file. For example, you can list the unused code of an application. Only applicable when shrinking.


列出被缩减删除的code。这个列表会被输出到output路径或者指定的路径文件下。例如,你可以列出应用中没有使用的code.只在缩减执行时才有效。



-whyareyoukeeping class_specification

Specifies to print details on why the given classes and class members are being kept in the shrinking step. This can be useful if you are wondering why some given element is present in the output. In general, there can be many different reasons. This option prints the shortest chain of methods to a specified seed or entry point, for each specified class and class member. In the current implementation, the shortest chain that is printed out may sometimes contain circular deductions -- these do not reflect the actual shrinking process. If the -verboseoption if specified, the traces include full field and method signatures. Only applicable when shrinking.


设置打印说明为什么要在缩减步骤中保留那些类和类成员。如果你想知道为什么一些元素在输出结果中依然存在,这个选项很有用。通常情况下,可能会有很多不同的原因。这个选项为每个指定的类和类成员打印最短的方法引用链。

在当前的实现机制下,这个方法链有时候会包含有删减的内容 - - 这些不会影响缩减的真实处理。如果指定了具体选项,踪迹会包含指定的所有field和method签名。只在缩减执行时才有效。


Optimization Options  优化选项

-dontoptimize

Specifies not to optimize the input class files. By default, optimization is enabled; all methods are optimized at a bytecode level.


指定不优化输入文件。默认情况下,优化是可用的。所有方法都会以字节码等级进行优化。


-optimizations optimization_filter

Specifies the optimizations to be enabled and disabled, at a more fine-grained level. Only applicable when optimizing. This is an expert option.


以更细颗粒度的等级指定什么时候优化什么时候不优化。只有在优化中才有效。这是一个专业级的选项。



-optimizationpasses n

Specifies the number of optimization passes to be performed. By default, a single pass is performed. Multiple passes may result in further improvements. If no improvements are found after an optimization pass, the optimization is ended. Only applicable when optimizing.


指定执行优化的次数。默认只优化一次。多次优化会对结果进行深度提升。如果在一次优化后发现没有可以提升的空间后,优化会停止。只有在优化的情况下此选项才有效。


-assumenosideeffects class_specification

Specifies methods that don't have any side effects (other than maybe returning a value). In the optimization step, ProGuard will then remove calls to such methods, if it can determine that the return values aren't used. ProGuard will analyze your program code to find such methods automatically. It will not analyze library code, for which this option can therefore be useful. For example, you could specify the method System.currentTimeMillis(), so that any idle calls to it will be removed. With some care, you can also use the option to remove logging code. Note that ProGuard applies the option to the entire hierarchy of the specified methods. Only applicable when optimizing. In general, making assumptions can be dangerous; you can easily break the processed code. Only use this option if you know what you're doing!


使方法失效(除非返回一个有被使用的值)。在优化中,如果确定这些方法的返回值没有被使用,proguard将不去调用这些方法。proguard会自动分析你的代码找到这样的方法。在这个选项使用的时候,它不会分析library代码,但这个选项的效果仍有用。

举例说明,你可以指定System.currentTimeMillis(),不被调用。在某些场景中,你可以用这个选项去消除logging日志代码。请注意,proguard允许此选项影响方法的整个层级。只在使用了优化选项时才有效。通常情况下,使用

assumptions是危险的,你会轻易的破坏代码结构。请只有在你知道你在做什么的时候下使用。


-allowaccessmodification

Specifies that the access modifiers of classes and class members may be broadened during processing. This can improve the results of the optimization step. For instance, when inlining a public getter, it may be necessary to make the accessed field public too. Although Java's binary compatibility specifications formally do not require this (cfr. The Java Language Specification, Third Edition, Section 13.4.6), some virtual machines would have problems with the processed code otherwise. Only applicable when optimizing (and when obfuscating with the -repackageclasses option).

Counter-indication: you probably shouldn't use this option when processing code that is to be used as a library, since classes and class members that weren't designed to be public in the API may become public.

指定在proguard处理时扩展类和类成员的访问权限。它能提升优化结果。例如,当内嵌一个public getter方法时,有必要让相关的field也是public的。虽然Java的二进制兼容性规范没有正式要求这么做,另外,有些虚拟机也可能在处理这样优化过得代码出现问题。只有在优化选项中(如果混淆了,也需要使用-repackageclasses选项)使用。

警告:你不应该在library项目代码中使用此选项处理代码,因为那些没有被设计成public的类和类成员可能会变成public.


-mergeinterfacesaggressively

Specifies that interfaces may be merged, even if their implementing classes don't implement all interface methods. This can reduce the size of the output by reducing the total number of classes. Note that Java's binary compatibility specifications allow such constructs (cfr. The Java Language Specification, Third Edition, Section 13.5.3), even if they are not allowed in the Java language (cfr. The Java Language Specification, Third Edition, Section 8.1.4). Only applicable when optimizing.

Counter-indication: setting this option can reduce the performance of the processed code on some JVMs, since advanced just-in-time compilation tends to favor more interfaces with fewer implementing classes. Worse, some JVMs may not be able to handle the resulting code. Notably:

  • Sun's JRE 1.3 may throw an InternalError when encountering more than 256 Miranda methods (interface methods without implementations) in a class.



合并所有interface接口,即使他们的实现类没有实现所有的接口方法。它能减少output里类的数量。需要指出的是,Java的二进制兼容性规范是允许这样的结构的,虽然java语言不允许这样的结构。只有在优化选项使用时有效。

警告:使用了此选项后的code在一些jvm中执行表现会降低。因为高级的运行时编译机制倾向于更多的接口,更少的实现类。更糟糕的时,一些jvms可能不能处理这种代码。特别是:

Sun's JRE 1.3将抛出一个InternalError,当遇到一个类有超过256个 Miranda methods (没有实现的接口方法)




Obfuscation Options

-dontobfuscate

Specifies not to obfuscate the input class files. By default, obfuscation is applied; classes and class members receive new short random names, except for the ones listed by the various -keep options. Internal attributes that are useful for debugging, such as source files names, variable names, and line numbers are removed.

指定不混淆输入文件。默认混淆是使用的,类和类成员获得一个新的短的随机名称,除了那些被-keep相关选项保护的。用于调试的内部属性,如资源文件名,变量名,行号都被删除。



-printmapping [filename]

Specifies to print the mapping from old names to new names for classes and class members that have been renamed. The mapping is printed to the standard output or to the given file. For example, it is required for subsequent incremental obfuscation, or if you ever want to make sense again of obfuscated stack traces. Only applicable when obfuscating.

打印类和类成员新旧名称的对应表。对应表被打印到output路径或者指定的路径。例如,后续增量混淆需要它,或者你想查看混淆后的日志。只有在混淆执行时有效。


-applymapping filename

Specifies to reuse the given name mapping that was printed out in a previous obfuscation run of ProGuard. Classes and class members that are listed in the mapping file receive the names specified along with them. Classes and class members that are not mentioned receive new names. The mapping may refer to input classes as well as library classes. This option can be useful for incremental obfuscation, i.e. processing add-ons or small patches to an existing piece of code. If the structure of the code changes fundamentally, ProGuard may print out warnings that applying a mapping is causing conflicts. You may be able to reduce this risk by specifying the option -useuniqueclassmembernames in both obfuscation runs. Only a single mapping file is allowed. Only applicable when obfuscating.


复用在以前混淆打印出的对应表。对应表包含的类和类成员名称不变。没有包含的获取新名称。对应表涉及input和libaray的类。这个选项对增量混淆很有用。例如,增量更新和补丁更新。如果代码的结构发生根本性的变化,proguard会发出使用对应表引起冲突的警告。你可一个通过在每次混淆时指定 -useuniqueclassmembernames 选项来降低这个风险。只能有一个对应表可以使用,只能在混淆时有效。


-obfuscationdictionary filename

Specifies a text file from which all valid words are used as obfuscated field and method names. By default, short names like 'a', 'b', etc. are used as obfuscated names. With an obfuscation dictionary, you can specify a list of reserved key words, or identifiers with foreign characters, for instance. White space, punctuation characters, duplicate words, and comments after a # sign are ignored. Note that an obfuscation dictionary hardly improves the obfuscation. Decent compilers can automatically replace them, and the effect can fairly simply be undone by obfuscating again with simpler names. The most useful application is specifying strings that are typically already present in class files (such as 'Code'), thus reducing the class file sizes just a little bit more. Only applicable when obfuscating.


指定一个文件设计有效的混淆名供类field和method使用。默认的的混淆名诸如a ,b 之类的。通过这个混淆字典,你可以指定保留关键字,或者外国标示符作为命名规则。空格,标点符号,重复的文字和#后面的注释是被忽略的。请注意,混淆字典很难提升混淆效果。像样点得编译器可以自动替换他们,而其成效又可以通过用更简单的命名方式替代。最有用的应用场景是指定存在于class的代表性的字符串(如‘Code’),因此混淆后的class文件大小会比默认混淆规则大一点。只在混淆时有效。



-classobfuscationdictionary filename

Specifies a text file from which all valid words are used as obfuscated class names. The obfuscation dictionary is similar to the one of the option -obfuscationdictionary. Only applicable when obfuscating.


指定混淆类名的命名规则。类似于-obfuscationdictionary.只在混淆时有效。



-packageobfuscationdictionary filename

Specifies a text file from which all valid words are used as obfuscated package names. The obfuscation dictionary is similar to the one of the option -obfuscationdictionary. Only applicable when obfuscating.


指定混淆包名的命名规则。类似于-obfuscationdictionary.只在混淆时有效。


-overloadaggressively

Specifies to apply aggressive overloading while obfuscating. Multiple fields and methods can then get the same names, as long as their arguments and return types are different, as required by Java bytecode (not just their arguments, as required by the Java language). This option can make the processed code even smaller (and less comprehensible). Only applicable when obfuscating.

Counter-indication: the resulting class files fall within the Java bytecode specification (cfr. The Java Virtual Machine Specification, Second Edition, first paragraphs of Section 4.5 and Section 4.6), even though this kind of overloading is not allowed in the Java language (cfr. The Java Language Specification, Third Edition, Section 8.3 and Section 8.4.5). Still, some tools have problems with it. Notably:

  • Sun's JDK 1.2.2 javac compiler produces an exception when compiling with such a library (cfr. Bug #4216736). You probably shouldn't use this option for processing libraries.
  • Sun's JRE 1.4 and later fail to serialize objects with overloaded primitive fields.
  • Sun's JRE 1.5 pack200 tool reportedly has problems with overloaded class members.
  • The class java.lang.reflect.Proxy can't handle overloaded methods.
  • Google's Dalvik VM can't handle overloaded static fields.


指定混淆时采用野蛮式的重载。很多field和methods可以有相同的名称,只要他们的入参和返回类型不同,只要符合java字节码(不只是他们的参数,只要符合java语言要求)。此选项可以让处理后的代码更加的小(更加的难以理解)。

只在混淆时有效。


警告:即使这种重载不符合java语言,但它符合java字节码规范。当然,一些工具处理它时还是会遇到问题。典型的如下:

Sun's JDK 1.2.2 javac 编译器当编译这样一个library的时候会产生异常。你应该不能用这个选项去处理library。

Sun's JRE 1.4 及以后的版本序列化重载的原始fields时会失败。

Sun's JRE 1.5 pack200 tool据说也会有重载的成员的相关问题。

java.lang.reflect.Proxy类不能处理重载的方法。

Google's Dalvik VM不能处理重载静态fields.


-useuniqueclassmembernames

Specifies to assign the same obfuscated names to class members that have the same names, and different obfuscated names to class members that have different names (for each given class member signature). Without the option, more class members can be mapped to the same short names like 'a', 'b', etc. The option therefore increases the size of the resulting code slightly, but it ensures that the saved obfuscation name mapping can always be respected in subsequent incremental obfuscation steps.

For instance, consider two distinct interfaces containing methods with the same name and signature. Without this option, these methods may get different obfuscated names in a first obfuscation step. If a patch is then added containing a class that implements both interfaces, ProGuard will have to enforce the same method name for both methods in an incremental obfuscation step. The original obfuscated code is changed, in order to keep the resulting code consistent. With this option in the initial obfuscation step, such renaming will never be necessary.

This option is only applicable when obfuscating. In fact, if you are planning on performing incremental obfuscation, you probably want to avoid shrinking and optimization altogether, since these steps could remove or modify parts of your code that are essential for later additions.

指定有相同名称的类成员使用相同的混淆名,不同名称的类成员用不同的混淆名称(针对每一个类成员泛型)。不用这个选项,更多的类成员会被混淆成类似于a,b这样的名字。这个选项会稍微的增加结果的大小,但它能确保这个混淆后的名字能给以后的增量混淆带来好处。

例如,有两个不同的接口包含有同样的方法名和泛型的方法。没有这个选项的时候,这个方法会在第一次混淆的时候拥有不同的方法名。如果一个后续添加的补丁中包含一个实现了这两个接口的类,proguard不得不在增量混淆中强制把这两个方法名在改为一个同样的名字。为了保持结果代码的功能完整性,原来混淆的代码需要做出改变。但在初始的混淆中有了这个选项,这种再改名的现象就不需要了。

这个选项只有在混淆时才有效。事实上,如果你计划执行增量更新,你应当避免缩减和优化,因为这些步骤可能会删除或者改变为以后增量代码预留的代码。



-dontusemixedcaseclassnames

Specifies not to generate mixed-case class names while obfuscating. By default, obfuscated class names can contain a mix of upper-case characters and lower-case characters. This creates perfectly acceptable and usable jars. Only if a jar is unpacked on a platform with a case-insensitive filing system (say, Windows), the unpacking tool may let similarly named class files overwrite each other. Code that self-destructs when it's unpacked! Developers who really want to unpack their jars on Windows can use this option to switch off this behavior. Obfuscated jars will become slightly larger as a result. Only applicable when obfuscating.


指定混淆时不生产混合方法名。默认的,混淆的方法名包含大小写的混合形式。它生成出完美运行的jars。但当这个jar在不区分大小写的系统(如windows)解压的时候,解压工具可能会覆盖相似文件名的文件。这样代码在解压的时候就损坏了。如果开发者想要在windows下解压jars,他们就可以使用这个选项去关闭混合命名行为。混淆的代码会稍微大一点。只有在混淆时有效。



-keeppackagenames [package_filter]

Specifies not to obfuscate the given package names. The optional filter is a comma-separated list of package names. Package names can contain ?, *, and ** wildcards, and they can be preceded by the ! negator. Only applicable when obfuscating.


不混淆指定规则的包名。过滤器选项是以逗号分隔额包名列表。包名可包含?, *, 和 **通配符,也可以在前面包含!作为非的含义。只有在混淆时有效。



-flattenpackagehierarchy [package_name]

Specifies to repackage all packages that are renamed, by moving them into the single given parent package. Without argument or with an empty string (''), the packages are moved into the root package. This option is one example of further obfuscating package names. It can make the processed code smaller and less comprehensible. Only applicable when obfuscating.

将所有重命名的包名重新包裹,把他们都移动到一个单独的父包目录下。如果不写入参[package_name]或者写为空字符串’’,所有包则都会被移动到根包下。这个选项使用的一个场景是深度混淆包名。它能让处理后的代码更小,更难读懂。只有在混淆时才有效。




-repackageclasses [package_name]

Specifies to repackage all class files that are renamed, by moving them into the single given package. Without argument or with an empty string (''), the package is removed completely. This option overrides the -flattenpackagehierarchy option. It is another example of furtherobfuscating package names. It can make the processed code even smaller and less comprehensible. Its deprecated name is -defaultpackage. Only applicable when obfuscating.

Counter-indication: classes that look for resource files in their package directories will no longer work properly if they are moved elsewhere. When in doubt, just leave the packaging untouched by not using this option.

将所有混淆的类文件重新打包到一个给定的单独的包下。如果不写入参[package_name]或者写为空字符串’’,则将包路径完全去除。它能让处理后的代码更小,更难读懂。它原来的名字是-defaultpackage.只在混淆时有效。

警告:那些需要在他们包路径中寻找资源文件的移至别处的类将不能工作。当你不确定时,还是不要使用这个选项好了。



-keepattributes [attribute_filter]

Specifies any optional attributes to be preserved. The attributes can be specified with one or more -keepattributes directives. The optional filter is a comma-separated list of attribute names that Java virtual machines and ProGuard support. Attribute names can contain ?, *, and** wildcards, and they can be preceded by the ! negator. For example, you should at least keep the Exceptions, InnerClasses, and Signatureattributes when processing a library. You should also keep the SourceFile and LineNumberTable attributes for producing useful obfuscated stack traces. Finally, you may want to keep annotations if your code depends on them. Only applicable when obfuscating.


保留指定的属性。属性可以用多个-keepattributes 来指定。添加项可以是java虚拟机和proguard支持的以逗号分隔的属性名称列表。属性名称可包含

 ?, *, 和**这样的通配符,也可以在前面使用 非符号!例如,当你处理一个library项目的时候,你至少要保留Exceptions, InnerClasses, 和 Signature属性(异常,内部类,泛型)。你也应当保留SourceFileLineNumberTable属性(源文件名,行号)以生成有用的混淆日志。最后,你可能想保留annotations (注解),如果你的代码依赖于它。只有在混淆时有效。


-keepparameternames

Specifies to keep the parameter names and types of methods that are kept. This option actually keeps trimmed versions of the debugging attributes LocalVariableTable and LocalVariableTypeTable. It can be useful when processing a library. Some IDEs can use the information to assist developers who use the library, for example with tool tips or autocompletion. Only applicable when obfuscating.

保留方法的参数和类型。这个选项实际上是debugging属性LocalVariableTableLocalVariableTypeTable的平衡使用。当处理library时,它很有用。一些IDEs能使用这些信息帮助那些使用了这个library的开发者们,例如提示或者自动补全工具。只有在混淆时有效。



-renamesourcefileattribute [string]

Specifies a constant string to be put in the SourceFile attributes (and SourceDir attributes) of the class files. Note that the attribute has to be present to start with, so it also has to be preserved explicitly using the -keepattributes directive. For example, you may want to have your processed libraries and applications produce useful obfuscated stack traces. Only applicable when obfuscating.

指定一个字符串常量替代SourceFile的内容(也可以是SourceDir)。请注意,指定的属性得使被-keepattributes 指定的。

你想让处理的library或者应用生成有用可读性高的混淆日志时,可以使用此配置项。只在混淆时有效。



-adaptclassstrings [class_filter]

Specifies that string constants that correspond to class names should be obfuscated as well. Without a filter, all string constants that correspond to class names are adapted. With a filter, only string constants in classes that match the filter are adapted. For example, if your code contains a large number of hard-coded strings that refer to classes, and you prefer not to keep their names, you may want to use this option. Primarily applicable when obfuscating, although corresponding classes are automatically kept in the shrinking step too.


指定 混淆那些与类名对应的字符串常量。如果没有设置过滤器,所有与类名对应的字符串常量都要混淆。如果有过滤器,只有匹配过滤器的常量会混淆。例如,假设你得代码中包含有大量的对应类的硬编码,你又不想保留他们的名字,你可以使用这个选项。需要提醒的是,混淆时优先考虑可用性,尽管有关联的类在缩减阶段也会被保护。



-adaptresourcefilenames [file_filter]

Specifies the resource files to be renamed, based on the obfuscated names of the corresponding class files (if any). Without a filter, all resource files that correspond to class files are renamed. With a filter, only matching files are renamed. For example, see processing resource files. Only applicable when obfuscating.


基于相关联的类文件(或者其他什么)的混淆名,混淆资源文件名。如果没有设置过滤器,所有资源文件名都要混淆。如果有过滤器,只有匹配过滤器的会混淆。可以参考processing resource files处理资源文件的例子。只有在混淆时才有效


-adaptresourcefilecontents [file_filter]

Specifies the resource files whose contents are to be updated. Any class names mentioned in the resource files are renamed, based on the obfuscated names of the corresponding classes (if any). Without a filter, the contents of all resource files updated. With a filter, only matching files are updated. The resource files are parsed and written using the platform's default character set. You can change this default character set by setting the environment variable LANG or the Java system property file.encoding. For an example, see processing resource files. Only applicable when obfuscating.

Caveat: You probably only want to apply this option to text files, since parsing and adapting binary files as text files can cause unexpected problems. Therefore, make sure that you specify a sufficiently narrow filter.

指定资源文件里的内容进行混淆。基于相关联的类文件(或者其他什么)的混淆名,任何与资源文件内容有关的类里的名称都会被重命名。没有过滤器,所有的资源文件都会被混淆。有了过滤器,只有匹配的才会处理。资源文件内容会按照平台的默认编码格式进行书写。你可以通过设置环境变量LANG或者java系统配置文件里的 file.encoding属性进行自定义。例子参考 processing resource files.只有混淆时才有效。


警告:你应当只让此选项适用于text文件,因为接卸和改编二进制文件为text文件会引起意想不到的问题。因此,确保你指定一个充分窄范围的过滤器。



Preverification Options  预校验选项

-dontpreverify

Specifies not to preverify the processed class files. By default, class files are preverified if they are targeted at Java Micro Edition or at Java 6 or higher. For Java Micro Edition, preverification is required, so you will need to run an external preverifier on the processed code if you specify this option. For Java 6, preverification is optional, but as of Java 7, it is required. Only when eventually targeting Android, it is not necessary, so you can then switch it off to reduce the processing time a bit.


不校验处理后的类文件。默认的,类文件是会被校验的,只要他们的版本是Java Micro Edition或java6以上版本。Java Micro Edition版本的代码是必须要校验的,所以如果你使用了这个选项,你也要运行一个额外的校验过程。java6校验是可选项,但是java7是必选项。只有在android下运行的代码,是不需要校验的,所有你可以关闭这个校验过程来减少一点点处理的时间。



-microedition

Specifies that the processed class files are targeted at Java Micro Edition. The preverifier will then add the appropriate StackMap attributes, which are different from the default StackMapTable attributes for Java Standard Edition. For example, you will need this option if you areprocessing midlets.


指定处理的类文件以Java Micro Edition运行。校验器会添加适当的StackMap属性,因为和Java Standard Edition默认的StackMapTable不一样。

当你处理midlets项目的时候,你需要用到这个选项。




General Options 常规选项

-verbose

Specifies to write out some more information during processing. If the program terminates with an exception, this option will print out the entire stack trace, instead of just the exception message.


输出处理期间更多的信息。如果处理中因为一个异常中断了,这个选项就会输出详细的日志,而不仅仅是异常信息。



-dontnote [class_filter]

Specifies not to print notes about potential mistakes or omissions in the configuration, such as typos in class names or missing options that might be useful. The optional filter is a regular expression; ProGuard doesn't print notes about classes with matching names.


不打印潜在的配置文件的错误或者遗漏,如类名的错别字,或者有用的选项。可选的过滤器是规则表达式;proguard不会打印符合过滤器的相关类信息。


-dontwarn [class_filter]

Specifies not to warn about unresolved references and other important problems at all. The optional filter is a regular expression; ProGuard doesn't print warnings about classes with matching names. Ignoring warnings can be dangerous. For instance, if the unresolved classes or class members are indeed required for processing, the processed code will not function properly. Only use this option if you know what you're doing!


不提示无法判断引用和其他重要的错误问题。可选的过滤器是规则表达式;proguard不会打印符合过滤器的相关类信息。忽略警示是危险的。

例如,如果无法判断的类和类成员确实是运行时需要的内容,则处理后的代码可能会无效。只有在你知道你做什么的时候使用。


-ignorewarnings

Specifies to print any warnings about unresolved references and other important problems, but to continue processing in any case. Ignoring warnings can be dangerous. For instance, if the unresolved classes or class members are indeed required for processing, the processed code will not function properly. Only use this option if you know what you're doing!


提示任何无法判断引用和其他重要的错误问题,但却继续执行处理流程而不中断。忽略警示是危险的。例如,如果无法判断的类和类成员确实是运行时需要的内容,则处理后的代码可能会无效。只有在你知道你做什么的时候使用。


-printconfiguration [filename]

Specifies to write out the entire configuration that has been parsed, with included files and replaced variables. The structure is printed to the standard output or to the given file. This can sometimes be useful for debugging configurations, or for converting XML configurations into a more readable format.


打印出build解析后执行的完整的proguard配置信息,包括包含的文件和替换的变量。这个结构会被写入output中或者指定的文件。在debugging配置或者转换XML为更易读的结构是会有用。



-dump [filename]

Specifies to write out the internal structure of the class files, after any processing. The structure is printed to the standard output or to the given file. For example, you may want to write out the contents of a given jar file, without processing it at all.


输出intput的原来包含的类的内部结构。这个结构会被写入output中或者指定的文件。

例如,你想输出给定的一个jar文件结构,在没有被处理的时候。 write out the contents of a given jar file



Class Paths

ProGuard accepts a generalization of class paths to specify input files and output files. A class path consists of entries, separated by the traditional path separator (e.g. ':' on Unix, or ';' on Windows platforms). The order of the entries determines their priorities, in case of duplicates.

Each input entry can be:

  • A class file or resource file,
  • An apk file, containing any of the above,
  • A jar file, containing any of the above,
  • An aar file, containing any of the above,
  • A war file, containing any of the above,
  • An ear file, containing any of the above,
  • A zip file, containing any of the above,
  • A directory (structure), containing any of the above.


Proguard接受广泛化的类路径来指定输入和输出文件。类路径可由多个条目组成,以传统的分隔符分隔(例如,Unix上用:  Windows上用;)。有多数的情况下,词条的顺序决定了他们的优先级。

路径文件可以是:

类文件或者资源文件,

apk文件,包含以上

jar文件,包含以上

aar文件,包含以上

war文件,包含以上

ear文件,包含以上

zip文件,包含以上

目录结构,包含以上



The paths of directly specified class files and resource files is ignored, so class files should generally be part of a jar file, an aar file, a war file, an ear file, a zip file, or a directory. In addition, the paths of class files should not have any additional directory prefixes inside the archives or directories.

直接在路径中指定的类文件和资源文件是被忽略处理的,所以类文件应当是jar,aar,war,ear,zip或者目录里的一部分。另外,类文件的路径应该没有任何附加的档案或目录前缀(不明白- -|)。

Each output entry can be:

  • An apk file, in which all class files and resource files will be collected.
  • A jar file, in which any and all of the above will be collected,
  • An aar file, in which any and all of the above will be collected,
  • A war file, in which any and all of the above will be collected,
  • An ear file, in which any and all of the above will be collected,
  • A zip file, in which any and all of the above will be collected,
  • A directory, in which any and all of the above will be collected.

output的对象可以是:

apk文件,包含类文件和资源文件。

jar文件,包含以上。

aar文件,包含以上。

war文件,包含以上。

ear文件,包含以上。

zip文件,包含以上。

目录,包含以上。



When writing output entries, ProGuard will generally package the results in a sensible way, reconstructing the input entries as much as required. Writing everything to an output directory is the most straightforward option: the output directory will contain a complete reconstruction of the input entries. The packaging can be almost arbitrarily complex though: you could process an entire application, packaged in a zip file along with its documentation, writing it out as a zip file again. The Examples section shows a few ways to restructure output archives.

当输出output的时候,proguard通常会以简单明了的方式重新打包结果,尽量按照input的时候重新打包。把所有东西输出到一个目录是最直接的方法:output目录将包含一个完成的input重构结构。打包可以随意的复杂化:你可以处理一个完整的应用,打包成zip和文档放在一起,然后再一起打包成zip输出。

例子单元有重构output档案的多个方法。restructure output archives


-injars base_in1.jar

-injars base_in2.jar

-injars base_in3.jar

-outjars base_out.jar


-injars  extra_in.jar

-outjars extra_out.jar



Files and directories can be specified as discussed in the section on file names below.

文件和目录可以按照下面文件名单元规则进行指定。


In addition, ProGuard provides the possibility to filter the class path entries and their contents, based on their full relative file names. Each class path entry can be followed by up to 7 types of file filters between parentheses, separated by semi-colons:

  • A filter for all aar names that are encountered,
  • A filter for all apk names that are encountered,
  • A filter for all zip names that are encountered,
  • A filter for all ear names that are encountered,
  • A filter for all war names that are encountered,
  • A filter for all jar names that are encountered,
  • A filter for all class file names and resource file names that are encountered.

此外,proguard提供基于全路径的内容过滤。路径可以包含以下7种类型的文件设置过滤选项:

aar,apk,zip,ear,war,jar,类名和资源名



If fewer than 7 filters are specified, they are assumed to be the latter filters. Any empty filters are ignored. More formally, a filtered class path entry looks like this:

如果少于7中类型被设定,那就假定只针对于后面的过滤类型。空的过滤器是被忽略的。更正式点,一个路径过滤器应该如下这样。


classpathentry([[[[[[aarfilter;]apkfilter;]zipfilter;]earfilter;]warfilter;]jarfilter;]filefilter)

Square brackets "[]" mean that their contents are optional.

[]的区域标示里面的内容是可选项


For example, "rt.jar(java/**.class,javax/**.class)" matches all class files in the java and javax directories inside the rt jar.

例如,"rt.jar(java/**.class,javax/**.class)" 表示匹配rtjar中在java和javax目录下的类文件。


For example, "input.jar(!**.gif,images/**)" matches all files in the images directory inside the input jar, except gif files.

"input.jar(!**.gif,images/**)”表示匹配images目录下的文件,不包括gif文件。

The different filters are applied to all corresponding file types, irrespective of their nesting levels in the input; they are orthogonal.

不同的过滤器可以对应所有的文件类型,与input的嵌套等级无关(即不管input是否包含过滤类型);他们是可相互交叉的。

For example, "input.war(lib/**.jar,support/**.jar;**.class,**.gif)" only considers jar files in the lib and support directories in the input war, not any other jar files. It then matches all class files and gif files that are encountered.

 "input.war(lib/**.jar,support/**.jar;**.class,**.gif)表示,只考虑lib,support文件夹下的jar。结果是,这个过滤器会会匹配遇到的所有类文件和gif。


The filters allow for an almost infinite number of packaging and repackaging possibilities. The Examples section provides a few more examples forfiltering input and output.

过滤器允许包含无限数量的包层级和重新打包的层级。示例单元提供了一些input和output的例子。


File Names

ProGuard accepts absolute paths and relative paths for the various file names and directory names. A relative path is interpreted as follows:

  • relative to the base directory, if set, or otherwise
  • relative to the configuration file in which it is specified, if any, or otherwise
  • relative to the working directory.

proguard允许文件名和目录名采用绝对路径和相对路径。相对路径会按如下方式进行解读:

与基本目录相关联,如果符合则确定,否则继续寻找

与指定的配置文件关联,如果符合则确定,否则继续寻找

与工作目录关联


The names can contain Java system properties (or Ant properties, when using Ant), delimited by angular brackets, '<' and '>'. The properties are automatically replaced by their corresponding values.

路径名可以包含java环境变量(或者ANT变量),以<>表示。环境变量会自动转换为相应的值。

For example, <java.home>/lib/rt.jar is automatically expanded to something like /usr/local/java/jdk/jre/lib/rt.jar. Similarly, <user.home> is expanded to the user's home directory, and <user.dir> is expanded to the current working directory.

例如,<java.home>/lib/rt.jar 会自动扩展为类似/usr/local/java/jdk/jre/lib/rt.jar. 同样的,<user.home>扩展为用户home目录。 <user.dir> 扩展为当前工作目录。

Names with special characters like spaces and parentheses must be quoted with single or double quotes. Each file name in a list of names has to be quoted individually. Note that the quotes themselves may need to be escaped when used on the command line, to avoid them being gobbled by the shell.

名称中包含有类似空格,括号的特殊字符得用单引号或者双引号表示。名称列表的每一个名称都得用引号区分出来。请注意,引号本身应当避免在命令行中使用,以免引号被shell吞噬。


For example, on the command line, you could use an option like '-injars "my program.jar":"/your directory/your program.jar"'.

例如,你可以在命令行上这样使用一个选项’-injars "my program.jar":"/your directory/your program.jar"'.



File Filters

Like general filters, a file filter is a comma-separated list of file names that can contain wildcards. Only files with matching file names are read (in the case of input jars), or written (in the case of output jars). The following wildcards are supported:

?

matches any single character in a file name.

*

matches any part of a filename not containing the directory separator.

**

matches any part of a filename, possibly containing any number of directory separators.




与常用的过滤器一样,文件过滤器也是包含通配符的以逗号分隔的文件列表。只有匹配的文件才会被读取(与input jar有关),写入(与output有关)。一些是支持的通配符:

?表示匹配任何单字符

*表示匹配文件名的任何部分,不包含目录

**匹配文件名的任何部分,即使名字中间包含任何多的目录


For example, "java/**.class,javax/**.class" matches all class files in the java and javax.

例如,"java/**.class,javax/**.class" 包含java,javax文件夹及子文件夹下的所有类文件。


Furthermore, a file name can be preceded by an exclamation mark '!' to exclude the file name from further attempts to match with subsequentfile names.

此外,文件名前可以使用!来排除后面的文件。


For example, "!**.gif,images/**" matches all files in the images directory, except gif files.

例如,"!**.gif,images/**" 匹配所有image目录下的文件,除了gif文件

The Examples section provides a few more examples for filtering input and output.

 filtering input and output  单元中有更多例子。


Filters

ProGuard offers options with filters for many different aspects of the configuration: names of files, directories, classes, packages, attributes, optimizations, etc.

A filter is a list of comma-separated names that can contain wildcards. Only names that match an item on the list pass the filter. The supported wildcards depend on the type of names for which the filter is being used, but the following wildcards are typical:

?

matches any single character in a name.

*

matches any part of a name not containing the package separator or directory separator.

**

matches any part of a name, possibly containing any number of package separators or directory separators.


Proguard为配置文件提供多方位的过滤器:文件名,目录,类,包,属性,优化等等。

过滤器是包含通配符的以逗号分隔的名称列表。只有匹配的名字才能通过过滤。支持的通配符依据过滤器使用的名称类型,但如下的通配符是通用的:

?匹配任意单个字符

*匹配包含在包和目录分隔符之间的任何部分

**匹配包含任何包,目录的任何内容


For example, "foo,*bar" matches the name foo and all names ending with bar.

例如,"foo,*bar”匹配叫foo的和以bar结尾的名字

Furthermore, a name can be preceded by a negating exclamation mark '!' to exclude the name from further attempts to match with subsequentnames. So, if a name matches an item in the filter, it is accepted or rejected right away, depending on whether the item has a negator. If the name doesn't match the item, it is tested against the next item, and so on. It if doesn't match any items, it is accepted or rejected, depending on the whether the last item has a negator or not.

此外,文件名前可以使用!来排除后面的文件。因此一个名字匹配后是接受还是拒绝,基于它是否有否决器。如果一个名字不匹配一个规则,它会尝试下一个,然后一直下去。如果它不匹配任何一个,它接受与否决定与最后是否有否决器。


For example, "!foobar,*bar" matches all names ending with bar, except foobar.

例如, "!foobar,*bar" 匹配所有以bar结尾的名字,但是不包含foobar.



Overview of Keep Options 

The various -keep options for shrinking and obfuscation may seem a bit confusing at first, but there's actually a pattern behind them. The following table summarizes how they are related:

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


为缩减和混淆提供的-keep相关选项乍一看有些混乱,但他们背后是有模式的。下图就展示了他们的关系。


Each of these -keep options is of course followed by a specification of the classes and class members (fields and methods) to which it should be applied.

每一个-keep选项都可以跟随一个类和类成员的限定规则。


If you're not sure which option you need, you should probably simply use -keep. It will make sure the specified classes and class members are not removed in the shrinking step, and not renamed in the obfuscation step.


  • If you specify a class, without class members, ProGuard only preserves the class and its parameterless constructor as entry points. It may still remove, optimize, or obfuscate its other class members.
  • If you specify a method, ProGuard only preserves the method as an entry point. Its code may still be optimized and adapted.


如果你不确定使用哪个,那就直接使用-keep选项。它将保证不会在缩减中删除你指定的类和类成员,也不会改变他们的名字。


如果你只指定了类,没有指定类成员。proguard只会保留类名和默认的无参构造器。它其他的类成员仍然会经历删除,优化,混淆的过程。

如果你只指定方法名,proguard只会保护方法名,它里面的代码仍然会优化和改编。


Class Specifications

A class specification is a template of classes and class members (fields and methods). It is used in the various -keep options and in the -assumenosideeffects option. The corresponding option is only applied to classes and class members that match the template.

The template was designed to look very Java-like, with some extensions for wildcards. To get a feel for the syntax, you should probably look at theexamples, but this is an attempt at a complete formal definition:


类规则是类和类成员限定的模板。它被运用于-keep和-assumenosideeffects属性中。相应的选项只会影响匹配模板的类和类成员。

模板被设计的近似于java的样子,外加一些扩展的通配符。为了对这个语法有个初步的认知,你应该去看看那些例子。下面是完整正式的模板定义:



[@annotationtype] [[!]public|final|abstract|@ ...] [!]interface|class|enum classname

    [extends|implements [@annotationtype] classname]

[{

    [@annotationtype] [[!]public|private|protected|static|volatile|transient ...] <fields> |

                                                                      (fieldtype fieldname);

    [@annotationtype] [[!]public|private|protected|static|synchronized|native|abstract|strictfp ...] <methods> |

                                                                                           <init>(argumenttype,...) |

                                                                                           classname(argumenttype,...) |

                                                                                           (returntype methodname(argumenttype,...));

    [@annotationtype] [[!]public|private|protected|static ... ] *;

    ...

}]

Square brackets "[]" mean that their contents are optional. Ellipsis dots "..." mean that any number of the preceding items may be specified. A vertical bar "|" delimits two alternatives. Non-bold parentheses "()" just group parts of the specification that belong together. The indentation tries to clarify the intended meaning, but white-space is irrelevant in actual configuration files.


[]里的内容标示为可选项。…意味着任何数量的内容可能会被在前面指定。|代表可选择。()则表示里面的内容是一个整体。缩进是为了便于你的观察,但空格本身是没有作用的。


  • The class keyword refers to any interface or class. The interface keyword restricts matches to interface classes. The enum keyword restricts matches to enumeration classes. Preceding the interface or enum keywords by a ! restricts matches to classes that are not interfaces or enumerations, respectively.


class关键字可影响interface和class。interface只约束interface类。enum关键字则约束枚举类。在interface和enum前加!则约束不是接口和枚举的类。


  • Every classname must be fully qualified, e.g. java.lang.String. Inner classes are separated by a dollar sign "$", e.g. java.lang.Thread$State. Class names may be specified as regular expressions containing the following wildcards:


类名需要使用全路径表示。例如,java.lang.String 内部类以$分隔,例如java.lang.Thread$State.类名匹配可以使用如下通配符:


  • ?
  • matches any single character in a class name, but not the package separator. For example, "mypackage.Test?" matches "mypackage.Test1" and "mypackage.Test2", but not "mypackage.Test12".
  • *
  • matches any part of a class name not containing the package separator. For example, "mypackage.*Test*" matches "mypackage.Test" and "mypackage.YourTestApplication", but not "mypackage.mysubpackage.MyTest". Or, more generally, "mypackage.*" matches all classes in "mypackage", but not in its subpackages.
  • **
  • matches any part of a class name, possibly containing any number of package separators. For example, "**.Test" matches all Testclasses in all packages except the root package. Or, "mypackage.**" matches all classes in "mypackage" and in its subpackages.



?匹配类名中单个任意字符,但不包含包分隔符。例如, "mypackage.Test?" 匹配 "mypackage.Test1" 和 "mypackage.Test2", 但不匹配 "mypackage.Test12".


*匹配类名中任意部分,不包含包分隔符。例如, "mypackage.*Test*" 匹配 "mypackage.Test" 和 "mypackage.YourTestApplication", 但不匹配”mypackage.mysubpackage.MyTest". 更常见的, "mypackage.*" 匹配在 "mypackage", 包下所有类,但不包含子包。


**匹配类名中任意部分,包含包分隔符。"**.Test" 匹配所有 除了根目录下的所有目录中包含的Test类 . "mypackage.**" 匹配”mypackage" 包及其子包种的所有类。


For additional flexibility, class names can actually be comma-separated lists of class names, with optional ! negators, just like file name filters.This notation doesn't look very Java-like, so it should be used with moderation.

为了添加方便,类名列表可以以逗号分开,也可以添加!否决器,就如同文件名过滤器一样。这个规则与java不是非常相似,所以请适度使用。



For convenience and for backward compatibility, the class name * refers to any class, irrespective of its package.


为了便捷和向后兼容,*可以表示任何类名,与它的包名无关。


The extends and implements specifications are typically used to restrict classes with wildcards. They are currently equivalent, specifying that only classes extending or implementing the given class qualify. Note that the given class itself is not included in this set. If required, it should be specified in a separate option.

extends 和implements关键字常与通配符关联使用。他们作用相等,指定只有那些extending或者implementing给定类的类才能通过。请注意,给定的类(被继承或实现的类)是不会包含在这个限定规则里的。若想把给定的类也指定,你得单独写个规则限定他。


The @ specifications can be used to restrict classes and class members to the ones that are annotated with the specified annotation types. An annotationtype is specified just like a classname.


@标示符可以用于限定那些使用指定注解的类和类成员。注解的指定和类名一样(即需要全路径)


Fields and methods are specified much like in Java, except that method argument lists don't contain argument names (just like in other tools like javadoc and javap). The specifications can also contain the following catch-all wildcards:


field和method的设定类似于java.除了那些没有入参名的方法(类似javadoc的注释)。规范可以包含下面的通配符使用:

<init>

matches any     constructor.

<fields>

matches any field.

<methods>

matches any method.

*

matches any field or method.


<init> 匹配所有构造器

<fields>匹配所有常变量

<methods>匹配所有方法

*匹配所有fields和方法


Note that the above wildcards don't have return types. Only the <init> wildcard has an argument list.

Fields and methods may also be specified using regular expressions. Names can contain the following wildcards:


请注意,以上的通配符不需要设置返回类型的。只有<init>通配符可设置入参。

field和menthods也可以用正规的的表达式表达。以下是可用的通配符:


?

matches any single character in a method name.

*

matches any part of a method name.

?匹配方法名单个任意字符

*匹配方法名任意部分


Types in descriptors can contain the following wildcards:

表示类型的可以是以下的通配符:


%

matches any primitive type ("boolean", "int", etc, but not "void").

?

matches any single character in a class name.

*

matches any part of a class name not containing the package separator.

**

matches any part of a class name, possibly containing any number of package separators.

***

matches any type (primitive or non-primitive, array or non-array).

matches any number of arguments of any type.




%匹配任何基本类型(如boolean,int等,但不能匹配void)

?匹配类名任何单个字符

*匹配不包含包分隔符的类名的任何部分

**匹配包含包分隔符的类名的任何部分

***匹配任何类型(基本的非基本的,数组的非数组的)

…匹配任意多任意类型的入参

Note that the ?, *, and ** wildcards will never match primitive types. Furthermore, only the *** wildcards will match array types of any dimension. For example, "** get*()" matches "java.lang.Object getObject()", but not "float getFloat()", nor "java.lang.Object[] getObjects()".


请注意,?,*,**不能匹配基本类型。除此之外,只有***能匹配任何规模的数组类型。

例如,** get*()" 匹配 "java.lang.Object getObject()", 但不匹配 "float getFloat()", 也不匹配 "java.lang.Object[] getObjects()".


Constructors can also be specified using their short class names (without package) or using their full class names. As in the Java language, the constructor specification has an argument list, but no return type.

The class access modifiers and class member access modifiers are typically used to restrict wildcarded classes and class members. They specify that the corresponding access flags have to be set for the member to match. A preceding ! specifies that the corresponding access flag should be unset.Combining multiple flags is allowed (e.g. public static). It means that both access flags have to be set (e.g. public and static), except when they are conflicting, in which case at least one of them has to be set (e.g. at least public or protected).ProGuard supports the additional modifiers synthetic, bridge, and varargs, which may be set by compilers.


构造器也可以通过设置短类名(不包含包名)或全类名指定。在java中,构造器有入参列表,但没有返回类型。

类和类成员的作用于也常用于约束通配符限定的类和类成员。通过他们限定匹配的成员。!否决符是不能被设置在作用域标识前的。混合使用作用域标识是可以的(例如 public static).这就意味着,两种作用域标示符都可以设置,除非他们之间有冲突,也就是说冲突的作用域标示符只能设置一个(例如,设置public或者protected).proguard也支持额外的可以在编译器上设置的标识如synthetic, bridge, 和 varargs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值