Note: This article refers to one of the documentation from the ProGuard directory of the Android SDK root directory. In addition to translation, some author’s actual verification is added. The article makes an explanation to Android obfuscation rule. The author is shallow, if there is a mistake, please understand! <@_@> Introduction to Android Code Obfuscation See Introduction to Android Code Obfuscation





5326.png

Input/Output Options Input/output options

-include filename Indicates the configuration file for the recursive import directory. -basedirectory directoryName -injars class_path Specifies the jars (or wars, EARS, zip, or directory structure) for the application to work with. The class files inside them are processed and written to the output jars. Any non-class files inside them are copied directly over but not processed. (Pay attention to filter and tune some IDE automatically generated files); -outjars class_path Specifies the name of the output jars(wars, EARS, zip, or directory structure). The processed jars specified by -injars will be written to the output jars specified. If outjars are not specified, no class files will be written. – libraryjars class_path don’t confuse the specified jar libraries (android projects introduced generally don’t confuse third-party libraries) – skipnonpubliclibraryclasses don’t confuse specifies a non-public jars calsses – dontskipnonpubliclibraryclasses don’t ignore the specified jars of non-public calsses (the default option), and the players want to – dontskipnonpubliclibraryclassmembers above Public class members (variables and methods) of the specified class library are not ignored. By default, ProGuard ignores them – keepDirectories [directory_filter] specifies the directory structure to keep, and by default deletes all directories to reduce the jar size. -target version Specifies the Java version. The version number can be one of 1.0,1.1,1.2,1.3,1.4,1.5 (or only 5), 1.6 (or only 6) or 1.7 (or only 7). By default, the version number of the class file remains the same. For example, you might want to upgrade a class file to Java 6 by changing its version number and pre-validating it. – forceProcessing forces processing of the input (-injars) jars. Even if the output jars are up-to-date. Determines whether the specified input, output, and timestamp of a configuration file or directory are up to date.

Keep Options Keep options

– keep [, modifier,… Class_specification Specifies the class and classmembers to keep (as a public library, all publicly accessible public methods should be kept) – keepClassMembers [, Modifier,… Class_specification Specifies class members to keep: variables or methods – keepClassesWithMembers [,modifier,…] Class_specification specifies the classes and class members to be retained, provided that all specified class members exist (no members were deleted during the compression phase, -keepnames class_specification [-keep allowallowclass_specification] Specifies classes and class members whose names are to be retained, provided that they are not deleted during the compression phase. Use for blur only – keepclassnames class_specification [-keepclassmembers allowallow_specification] Specifies the class member whose name is to be retained, provided that it has not been deleted during the compression phase. Only used to deal with the fuzzy – keepclasseswithmembernames class_specification [- keepclasseswithmembers allowshrinking class_specification abbreviations] Specifies the class member whose name you want to keep, provided that all specified class members exist after the compression phase. For obfuscation only -printseeds [filename] specifies an exhaustive list of classes and class members matched by the various -keep options. The list is printed to standard output or to a given file. This list can be used to verify that the expected class members are actually found, especially if you use wildcards. For example, you might want to list all the applications or all the applets you have saved.


Overview of Keep Options

scope Preserves the specified class and member The specified class or member is retained only if it has not been deleted during the compression phase
Class and class members -keep -keepnames
Class members only -keepclassmembers -keepclassmembernames
Classes and class members (provided the members exist) -keepclasseswithmembers -keepclasseswithmembernames
  • Beginners are advised to use -keep if they are not sure about the keep option. This is easier and less likely to confuse code.
  • If only the class is specified to be preserved, its members can also be compressed, optimized, or obfuscated.
  • If the specified class member is retained, other code may also be compressed, optimized, or obfuscated

Keep command modifiers [,Modifier,…] :

Can be used after the keep, keepClassmembers, keepClasseswithmembers commands

  • Allowshrinking specifies that objects may be compressed, even if they are preserved by the Keep option. If the specified objects are not required, they may be removed (in the compression step). Conversely, if they are necessary, they may not be optimized or confused.

    Such as: ClassOneThree not referenced in the code, is a no classes used. – keep class. Com dev. Demo. One. ClassOneThree * {*; } -keep keeps the upper ClassOneThree, but using the allowOneThree modifier will change that. The following commands will create the same effect: ClassOneThree was removed during the compression phase; it wasn’t retained because it wasn’t referenced. -keep,allowshrinking class com.dev.demo.one.ClassOneThree*{*; } -keepnames class com.dev.demo.one.ClassOneThree*{*; }

  • Allowoptimization specifies that objects may be optimized even if they are retained by the Keep option. The specified object may be changed (tuning step), but may not be obfuscated or deleted. This modifier is useful only for implementing exception requirements.

  • Allowobfuscation specifies that objects may be confused, even if they are reserved by KEEP. The specified object may be renamed, but may not be deleted or optimized. This modifier is useful only for implementing exception requirements.

Shrinking Options Compression options

Compression is turned on by default. Compression removes unused classes and class members, except for those listed by the various “-keep” options and the classes they directly or indirectly depend on. The compression step is performed after each optimization step, because some optimizations may result in more classes and class members that can be deleted. -dontshrink turns off compression. -printUsage [filename] lists the unused code and outputs it to the specified file. – Whyareyoukeeping class_specification Prints whya specified class retains details about its classes and class members during the compression phase


Optimization Options optimizations

Optimization is enabled by default; . All methods are optimized at the bytecode level. -dontoptimize Disable optimizations. – Optimization_filter Specifies optimizations of a higher level, only for optimizations. – Optimizationpasses n Specifies the number of optimizations, 1 by default. Code can be further optimized multiple times, and if there is no improvement after one optimization, the optimization ends. Used only in optimization phase – AssumenosideEffects class_specification indicates class methods that do not have any sideeffects. These methods are removed during optimization if it is determined that they are not being called or that the return value is not being used. ProGuard analyzes program code beyond the outgoing code. If you specify the System.currentTimemillis () method, any idle calls to it will be deleted. Only practical and optimized. Careful! – AllowAccessModification indicates that access modifiers for classes and class members are allowed to be modified, which can improve optimization results. – mergeinterfacesaggressively instructions allow merging interface, their timely implementation class does not implement all the interface methods. This reduces the size of the output by reducing the total number of classes. Only useful for optimization


Obfuscation Options confusion

Obfuscation is turned on by default. Obfuscation turns class and class member names into short random names, except for classes and class members protected by various “-keep” options. Internal attributes useful for debugging (source file names, variable names, line numbers) are removed. -dontobfuscate Disables obfuscation. -printmapping [filename] Prints the mapping between the old name and the renamed class and the new name of the class member. The mapping can be output to the specified file. Only used for obfuscation -applymapping [filename] Specifies that the file is a mapping file. Classes and class members listed in the mapping file receive the specified name, and classes and class members not mentioned in the file receive the new name. – obfuscationDictionary [filename] Specifies a text file in which all valid words are used as obfuscation fields and method names. By default, short names such as “a” and “b” are used as obfuscation names. Using a fuzzy dictionary, you can specify lists of reserved keywords, or identifiers with exotic characters, such as: ignore Spaces, punctuation marks, comments after duplicates, and # symbols. Note that fuzzy dictionaries do little to improve obfuscation. Some compilers can replace them automatically, and simply undo the effect by obfuscating them again with simpler names. The most useful is to reduce the size of the class file by specifying strings that normally already exist in the class file (for example, ‘Code’). Only for obfuscation processing. – classobfuscationdictionary [filename] to specify a text file, which all effective word confusion is used as the name of the class. Similar to -obfuscationDictionary. Only for obfuscation processing. – packageobfuscationdictionary [filename] to specify a text file, which all valid term is used as a confusing package name. Similar to -obfuscationDictionary. Only for obfuscation processing. – Overloadaggressively indicates deep overload confusion. This option may cause methods and attributes with different parameters and return types to get the same name after obfuscation. This option makes the code smaller (and harder to understand) and is only useful for obfuscation handling

– useuniqueclassmembernames appointed as members of the class with the same name assignment confusion with the same name, and for a different name (signature) for each given class members confused class members assign a different name. Without this option, more class members can be mapped to the same short name, such as ‘a’, ‘b’, etc. So the option slightly increases the size of the generated code, but it ensures that the saved obfuscation name map can always be respected in subsequent incremental obfuscation steps.

– no generate mixed case dontusemixedcaseclassnames confuse the name of the class. By default, obfuscated class names can contain a mixture of uppercase and lowercase characters. Only for obfuscation processing.

-keeppackagenames [package_filter] Specifies not to confuse the given packagename. Package_filter is a comma-separated list of package names. The package name can contain? , *, ** wildcard. Only for obfuscation processing.

– flattening the flattening list [package_name] moves all renamed packets into a given packet for repackaging. If there are no parameters or an empty string, the packet is moved to the root packet. This option further obliquates packet names and makes code code even harder to understand. Only for obfuscation processing. -repackageclasses [package_name] repackages all renamed class files and moves them to the given package. If there are no arguments or an empty string in the package, the package is removed completely. This option overrides the -flattenpackageHierarchy option. It makes the processed code smaller and less understandable. Its deprecated name is -defaultPackage. Only for obfuscation processing. -keepAttributes [attribute_filter] Specifies any optional attributes to keep. . You can specify attributes using one or more -keepAttributes directives. Attribute_filter is a comma-separated list of attribute names. If your code depends on annotations, you may want to keep them. Only for obfuscation processing. – keepparameterNames Specifies the reserved parametername and method type. This option actually preserves the debug properties LocalVariableTable and the clipped versions of LocalVariableTypeTable. It is useful when working with libraries. Some ides can use this information to help developers working with libraries, for example using tooltips or autocomplete. Only for obfuscation processing. – renamesourcefileattribute [string] specified in the class file SourceFile attribute for the constant strings (and SourceDir attribute). Note that the attribute must exist at the beginning, so it must also be explicitly reserved using the -keepAttributes directive. For example, you might want to make the libraries and applications you work with generate useful obfuscated stack traces. Only for obfuscation processing. -adaptclassstrings [class_filter] Confuses the string constants corresponding to the class name. If there is no filter, all the string constants corresponding to the class name are matched. If filter is used, only the string constants in the class matched by filter are matched. Only for obfuscation processing. – adaptResourcefilenames [file_filter] Specifies the resourcefile to be renamed based on the obfuscated name of the corresponding class file (if any). If there is no filter, rename all resource files corresponding to the class file. Use filters to rename only matching files. Only for obfuscation processing. – adaptresourcefilecontents [file_filter] specifies the resource file to update its content. Rename any class names mentioned in the resource file based on the obfuscated name (if any) of the corresponding class. Without filters, the contents of all resource files are updated. Use filters to update only matching files. 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. Only for obfuscation processing.


Preverification Options Prospective validation

Pre-validation is enabled by default. Improves VM loading efficiency. – DontPreVerify disables pre-validation – Microedition specifies the class files that have been processed for Java Micro Edition. Preverifier then adds the appropriate StackMap attributes, which are different from the Default StackMapTable attributes of Java Standard Edition. For example, you need this option if you are working with midlets.


General Options General options

-verbose Prints detailed information during obliquation and the entire stack if an exception terminates. -dontnote [class_filter] does not print possible errors or missing comments in configuration classes, such as misspellings in class names, or missing options that might be useful. Optional class_filter is a regular expression; ProGuard does not print comments about classes with matching names. -dontwarn [class_filter] does not issue a warning for incomplete references in a specified class or package. -ignorewarnings ignorewarnings and continue processing. -printconfiguration [filename] prints configuration information to the specified file. -dump [filename] prints the internal structure of the class file to the specified file


Class Paths

Class_paths indicates the input/output file paths of the options -injars, -outjars, or -libraryjars. ProGuard accepts generalization of the classpath. Consists of a series of files and separators (‘:’ on Unix, ‘on Windows; ‘); The order of the files determines the priority. The inputs may include:

  • Class file or resource file;
  • Jar files, which can contain any of the above files;
  • War file, which can contain any of the above files;
  • Ear file, which can contain any of the above files;
  • Zip file, which can contain any of the above files;
  • Directory structure containing any of the above files.

Directly specifying the path to a class file or resource file is ignored; the class file can be a JAR file, war, EAR, ZIP, or part of a directory structure. In addition, the path to a class file should not have any other directory prefix in the archive or directory.

Outputs may include:

  • Jar files, which contain all of the class files or resource files being processed;
  • War file, which contains any of the above files;
  • Ear file, containing any of the above files;
  • Zip file containing any of the above files;
  • Directory structure containing any of the above files.

ProGuard packages the output in a reasonable form and reconstructs the input file as needed. It is the easiest way for ProGuard to write all classes to the output directory, which contains a complete refactoring of the input class. Packages can be arbitrarily complex and can process the entire application, and packages and their documents in zip files will be processed again as ZIP files.

ProGuard allows the use of filters in filenames. They can filter some files or their contents relative to the full filename. The filters are between parentheses (). Separated by “:

  • Filter all zip file names;
  • Filtering of all EAR file names;
  • Filter all war file names
  • Filtering of all JAR file names;
  • For all class file names, resource file names.

If there are fewer than five filters in parentheses, they are assumed to be the last filter, and empty filters are ignored in the following format: classpathentry([[[[zipfilter;]earfilter;]warfilter;]jarfilter;] Filefilter ([]) indicates that its content is optional.

rt.jar(java/**.class,javax/**class)
Rt. jar file, all folders Java, javax all class filesinput.jar(! **.gif,images/**)# matches all files in input.jar except.gif in the images folderCopy the code
# Different filters can be applied to all corresponding types at the same time; They intersect regardless of their nesting, right
input.war(lib/ * *.jar.support/ * *jar;**class,**.gif) 
# contains jar files in lib, support and all. Class and. GIF files in itCopy the code

Some examples:

All output classes and resources will be merged into a JAR file. -injars classes
-injars in1.jar
-injars in2.jar
-injars in3.jar
-outjars out.jar
# merge the classes directory, in1.jar, in2.jar, in3.jar refactoring into out.jarCopy the code
If you want to preserve the structure of the input, you can output it to the directory structure (or WAR, EAR, zip). -injars in1.jar
-injars in2.jar
-injars in3.jar
-outjars out
The input file can be built in the out directory with the original file nameCopy the code

Use -injars and -outjars in groups to flexibly combine jars(Wars, EARS, Zips, or directories) into different jars(Wars, EARS, Zips, or directories) :

-injars base_in1.jar
-injars base_in2.jar
-injars base_in3.jar
-outjars base_out.jar

-injars extra_in.jar-outjars extra_out.jar
The # base_in*.jar file is merged into the base_out.jar file, and the extra_in.jar file is merged into the extra_out.jar file.Copy the code
# filter out all files under all imagesinjars  in.jar(! images/**)-outjars out.jar
# ignore irrelevant Java runtime classes <> refers to the system variable Java HOME (JAVA_HOME) -libraryjars <java.home>/lib/rt.jar(java/**,javax/**)Copy the code
-injars  in.jar
-outjars code_out.jar(**.class)
-outjars resources_out.jar
The # **.class file will be exported to the code_out.jar file, and all other files will be exported to the resources_out.jar file.Copy the code

File Names (File Names)

ProGuard accepts absolute and relative paths as file or pathnames. The relative path rule is:

  • First relative to base path, if not set:
  • Relative to the specified configuration path, if not:
  • Relative to the working directory.

The name can contain Java system configuration, wrapped in “<>” brackets. The system configuration will automatically replace them:

"<java.home>/lib/rt.jar"Will be interpreted as"/usr/local/java/jdk/jre/lib/rt.jar."
"<user.home>"Represents the user's Home directory"<user.dir>"Interpreted as the current working directoryCopy the code

Note: Special character names with Spaces and parentheses must be quoted in single or double quotation marks, and each filename in the name list must be quoted separately. The quotes themselves may need to be escaped on the command line to avoid shell misunderstandings


File Filters

Reference – adaptresourcefilenames, – adaptresourcefilecontents

“File_filter” is a list of Filters that can be separated by commas (“,”). Only matched files are read. The following wildcard characters are supported:? Matches a single character; * Matches any number of characters, excluding directory delimiters; ** matches any number of characters, excluding directory separators; ! Indicates no.

Java /**. Class,javax/**. Class // matches the Java and javax directories and allkeep class org.codehaus.jacksonMaintain. * / /org.codehaus.jacksonThe following class files do not include the class files in their subpackages
-keep class org.codehaus.jackson. * * / / keeporg.codehaus.jacksonAll of the following class files, including the class files in their subpackages
! **.gif,images/** Matches all files under the images directory, but not.gif files -injars  in.jar(! images/**) // Specifies the input JAR package, but removes all files under the images directoryCopy the code

Filter

ProGuard allows many options for configuration (files, directories, classes, packages, properties, optimizations… Etc.) using filters. Use commas (“,”) to separate them.

"foo,*bar"Matches foo files, and all names ending in bar.! "" Foobar,*bar matches all bar ending names except foobar.Copy the code

Class Specifications template

A class specification is a writing template for a class and its members. This is used mainly after the -keep, -assumenosideeffects options. It makes the options apply only to classes and class members that match the template. The specification looks like Java syntax, with some wildcards. Let’s look at the class specification format:

[@annotationtype] [[!]public|final|abstract|@... ] [!] interface|class|enum classname [extends|implements [@annotationtype] classname] [{ [@annotationtype] [[!]public|private|protected|static|volatile|transient ... ]  
       |
                                                                      (fieldtype fieldname);
    [@annotationtype] [[!]public|private|protected|static|synchronized|native|abstract|strictfp ... ]  
       |
                                                                                           <init>(argumenttype,...) |
                                                                                           classname(argumenttype,...) | (returntype methodname(argumenttype,...) ); [@annotationtype] [[!]public|private|protected|static ... ] *; . }]Copy the code
Description:

“[] “Square brackets indicate that the contents are optional; “…” The ellipsis indicates that there are many options available; “|” vertical bar dividing different choice “()” a regular bold parenthesis said to belong to the same set of attributes

  • The class keyword indicates any class or interface, interface indicates only the interface, and enum indicates only enumeration. Interface,enum add a “!” Indicates neither neither interface nor enumeration.
  • Each classname must be a full name, such as java.lang.String and com.example. Classname. Classname can also be a regular expression containing some of the following wildcards:

    ? The question mark matches a single character, but cannot be a package name separator; Such as: “mypackage. Test?” , can match “mypackage.Test1”, “mypackage.Test2”, but cannot match “mypackage.Test12”;

    * A single asterisk can match any number of characters, except for package separators, such as: “Mypackage. * the Test *” to match “mypackage. Test, mypackage. YourTestApplication”, but can’t match “mypackage. Mysubpackage. MyTest”; “Mypackage.*” matches classes under the package mypackage, but does not include classes in its subpackages; The ** double star matches any number of characters, including the delimiter of the package name; For example, “**.Test” matches all Test classes, and “mypackage.*” matches all subclasses of the package mypackage, including its subpackage classes.

  • Extends, implements indicates a particular class, which is eligible if it extends or implements the specified class (interface).

  • The @ indicates the class or class member that is annotated by the annotation type. The annotation type is specified as well as the class name.
  • Class members and methods are similar to Java syntax, and method parameters, like Javadoc, do not contain parameter names. Members and methods can also contain wildcards:

    matches the constructor;

    matches member variables;

    matched the method; * Matches any member and method; These don’t have any return types, only ”

    ” has a list of arguments. Member variables and methods can also be regular expressions that contain wildcards. Can contain the following wildcards:? Matches any single character in the method; * Matches any multiple characters in a method; The type can contain primitive types in the following wildcard % matching methods (” Boolean “, “int”… Void “); ? Matches a single character in the class name; * Matches multiple characters in the class name, excluding the package delimiter; ** Matches multiple characters in the class name, including the package separator; *** Matches primitive type, non-primitive type, array, non-array — matches any number and category of arguments. Note:? , *, ** do not match the original type, only *** can match; For example: “** get*()” matches “java.lang.object getObject()” does not match “float getFloat()” nor does it match “java.lang.object [] getObjects()”;



  • Constructors can have short names (excluding the package name) or full names (including the package name); Constructors in Java can have arguments but no return types.
  • You can set class, class member access modifiers (public,private…) , which usually help restrict wildcard classes and members. Only classes or members with the specified modifier can be matched. !” Say not. Allow multiple flags (“public static”), but only one if they conflict (e.g., public and private)

ProGuard supports synthetic, bridge, and Varargs modifiers set by the compiler.

Here are some simple examples:

# preserve all public decorated members and methods in class ClassOneOne
-keepclassmembernames class com.dev.demo.one.ClassOneOne {
    public *;
}
# preserve the public modifier constructor in ClassOne
-keep class com.dev.demo.ClassOne {
    public <init>();
}
Class ClassTwoTwo: public: int
-keep class com.dev.demo.two.ClassTwoTwo {
    public <init>(int);
}

Class ClassTwoThree preserves the public and private class member variables
-keepclassmember class com.dev.demo.two.ClassTwoThree {
    public <methods>;
    private <fields>;
}
Keeps the ClassTwoThree subclass with its members and methods
-keep class * extends com.dev.demo.two.ClassTwoThree {*; }# preserves the class prefix ClassOne and its members and methods
-keepnames class com.dev.demo.one.ClassOne*{*; }ClassTwoTwoInner keeps members and methods in ClassTwoTwoInner
-keep class com.dev.demo.two.ClassTwoTwo$ClassTwoTwoInner{*; }Copy the code