Zelix KlassMaster - Documentation
 

The exclude Statement

The ZKM Script exclude statement excludes the names of specified objects from being renamed by the Zelix KlassMaster™ obfuscate statement. Successive exclude statements have a cumulative effect. Once an exclusion has been set its effect can be

The remainder of this page is organized into the following sections.

Examples and Explanation

exclude statement parameters may be loosely categorized into the following groups

Package exclude parameters

Any package name matching a package exclusion parameter is excluded. If a package level is specified by a simple "*" wildcard then it matches one or more levels. If the package parameter is a component of a class, field, method or class suffix exclude parameter and the package parameter is followed by a "^" then the name of the enclosing package is also excluded. Note that a package name specification always ends with a ".". If a package name specification ends with ".." then it specifies that package and all of its sub-packages.
exclude pack1.pack2. and  //exclude the package "pack1.pack2"
        *.           and  //exclude all packages
        p*1.*.p*1.   and  //exclude any package matching "p*1.*.p1"
        pack2.*.     and  //exclude all the sub-packages of "pack2"
        pack3..      and  //exclude "pack3" and all sub-packages of "pack3"
        (pack4.*. && !(pack3.pack0. || pack3.pack2.)); //exclude all the sub-packages of "pack4" except for "pack0" and "pack2"

Class exclude parameters

Put informally (with mandatory components in bold), the syntax is:
<classAnnotations> <classModifiers> "<archiveQualifier>"!<packageQualifiers>.<className> <containingClause> <extendsClause> <implementsClause>;

For a class name to be excluded, all of the following must be true of a class:
  • Its annotations must match any specified annotations.
  • Its modifiers (e.g. public final) must match all parameter modifiers. So if the parameters are public abstract !interface then the class must be public, abstract and NOT an interface to be excluded.
  • If the parameter has an archive qualifier then the class must be contained in an archive which matches that archive qualifier.
  • Its package qualifiers must match any specified package exclude parameter component (see Package exclude parameters). If there is no package exclude parameter component then the class must be in the default package.
  • Its unqualified name must match the specified class name specification.
  • If the parameter has a containing clause then the class must contain members which match the specified class
  • If the parameter has an extends clause then the class must be a subclass of the specified class
  • If the parameter has an implements clause then the class must directly or indirectly implement all of the specified interfaces
If the class parameter is a component of a field or method exclude parameter then a final "^" tag after the class name specification causes the enclosing class to be excluded.

If a class exclusion parameter's class name specification is followed by a "+" tag then the parameter also causes the names of all the fields and methods of the class to be excluded.
exclude *          and         //exclude all classes in the default package
        *.Class1   and         //exclude all classes with the unqualified class name "Class1"
        pack1.pack2..*   and   //exclude all classes in "pack1.pack2" or any of its sub-packages
        public !final *.* and  //exclude all public non-final classes
        //exclude all "public abstract" classes that have an unqualified name matching "C*s" and extend "pack1.Class1".
        package abstract *.C*s extends pack1.Class1 and 
        //exclude all classes in packages that start with the character "p" and also exclude the names of the enclosing packages.
        p*.^*     and 
        "MyJar*.jar"!*.* and //exclude all classes contained in a JAR file with a name matching "MyJar*.jar"
        //exclude all classes that implement Serializable and also exclude all field and method names
        *.* + implements java.io.Serializable and 
        //exclude names of all classes that start with "Class" except for "Class0" and "Class1"
        *.(Class* && !(Class0 || Class1)) and 
        @*.MyAnnotation0 *.*  and //exclude all classes annotated which an annotation matching *.MyAnnotation0
        *.* containing{native *(*)};  //exclude all classes containing a native method

Field exclude parameters

Put informally (with mandatory components in bold), the syntax is:
<classAnnotations> <classModifiers> "<archiveQualifier>"!<packageQualifiers>.<className> <extendsClause> <implementsClause>
    <fieldAnnotations> <fieldModifiers> <fieldType> <fieldName>;

For a field name to be excluded, all of the following must be true:
  • Its containing class must match any class exclude parameter component (see Class exclude parameters).
  • Its annotations must match any specified field level annotations.
  • Its modifiers (e.g. public volatile) must match all parameter field modifiers. So if the parameters are public static !transient then the field must be public, static and NOT transient to be excluded.
  • Its type (e.g. int[] or java.lang.String) must match the parameter field type if it exists.
  • Its name must match the parameter field name.
exclude *.* *   and //Exclude all field names
        *.Class1 !transient int f* and //Exclude all non-transient "int" field names matching "f*" 
                                       //in classes with the unqualified name "Class1"
        public *.^*^ public volatile * and //Exclude all "public volatile" fields in
                                           //public classes.
                                           //Also exclude the containing package and class names.
        "MyJar*.jar"!*.* * and //exclude all fields contained in a JAR file with a name matching "MyJar*.jar"
        *.* @*.MyAnnotation0 *;  //Exclude all fields annotated with a class matching *.MyAnnotation0.

Method exclude parameters

Put informally (with mandatory components in bold), the syntax is:
<classAnnotations> <classModifiers> "<archiveQualifier>"!<packageQualifiers>.<className> <extendsClause> <implementsClause>
    <methodAnnotations> <methodModifiers> <methodName>(<argumentTypes>) <throwsClause> +signatureClasses;

For a method name to be excluded, all of the following must be true:
  • Its containing class must match any class exclude parameter component (see Class exclude parameters).
  • Its annotations must match any specified method or method parameter level annotations.
  • Its modifiers (e.g. public native) must match all parameter method modifiers. So if the parameters are public static !synchronized then the method must be public, static and NOT synchronized to be excluded.
  • Its name must match the parameter method name.
  • Its argument types (e.g. int[], java.lang.String) must match the parameter argument types if they exist. (A single parameter argument type of "*" matches any method argument types including no arguments.) If the parameter has no argument type then the method must take no arguments.
  • Its throws clause must contain all the classes specified in the exclude parameter's throw clause. So, if the exclude parameter's throws clause is throws java.io.IOException then the method must throw java.io.IOException or one of its subclasses to be excluded.

For consistency, the exclude statement supports the special method names <init> and <clinit> which represent constructor and class initializer method names respectively. However, because constructor and class initializer names cannot be obfuscated, the syntax has no practical application for this statement.

If a method exclude parameter ends with the keyword +signatureClasses then, for each matching method, the fully qualified class names of the method's return and parameter types are also excluded from obfuscation. Types which are primitive are ignored. So, if a matching method has the signature pack1.Class1 method1(pack2.Class2) then the +signatureClasses flag has the effect of excluding the fully qualified names:
  • pack1.Class1 (because it is the return type of a matching method) and
  • pack2.Class2 (because it is a parameter type of a matching method)
exclude *.* *(*)           and  //Exclude all method names
        *.* !static m*()   and  //Exclude all non-static methods taking no parameters with names matching "m*"
        //Exclude all "native" methods. Also exclude the containing package and class names.
        *.^*^ native *(*)  and  
        *.* *(*) throws java.io.IOException and  //Exclude all methods that throw java.io.IOException. 
        //Exclude the names of all "abstract" methods that take a single String.
        *.* abstract *(java.lang.String) and 
        pack1.Class1 *(*) +signatureClasses and //Exclude all method names in pack1.Class1 along with 
                                                //the matching methods' return and parameter types
        //Exclude all the methods of any class implementing "Serializable" in a package that matches "pack1.*"
        pack1.* implements java.io.Serializable *(*) and 
        //Exclude all methods annotated with a class matching *.MyAnnotation0.
        "MyJar*.jar"!*.* *(*) and //exclude all methods contained in a JAR file with a name matching "MyJar*.jar"
        *.* @*.MyAnnotation0 *(*);

Method prefix exclude parameters

If a method name starts with the method prefix exclude parameter
  • its specified prefix is excluded from being renamed
  • if a field X can be found in
    • in the class containing the matching method or
    • in the hierarchy of the class containing the matching method
    that has name matching the non-prefix part of the matching method's name then the non-prefix part of the matching method's name will be renamed to the new name of the field X.
For example, let's say we have a class that contains a method named getTime() and a field named time and we specify a method prefix exclude parameter get<link>(). The prefix is get. If the field time is renamed to x then the method getTime() will be renamed to getX();

Put informally (with mandatory components in bold), the syntax is:
<classAnnotations> <classModifiers> "<archiveQualifier>"!<packageQualifiers>.<className> <extendsClause> <implementsClause>
    <methodAnnotations> <methodModifiers> <prefix><methodName>(<argumentTypes>) <throwsClause>

For a method name prefix to be excluded, all of the following must be true:
  • Its containing class must match any class exclude parameter component (see Class exclude parameters).
  • Its annotations must match any specified method or method parameter level annotations.
  • Its modifiers (e.g. public native) must match all parameter method modifiers. So if the parameters are public static !synchronized then the method must be public, static and NOT synchronized to be excluded.
  • Its name must start with the specified prefix.
  • Its argument types (e.g. int[], java.lang.String) must match the parameter argument types if they exist. (A single parameter argument type of "*" matches any method argument types including no arguments.) If the parameter has no argument type then the method must take no arguments.
  • Its throws clause must contain all the classes specified in the exclude parameter's throw clause. So, if the exclude parameter's throws clause is throws java.io.IOException then the method must throw java.io.IOException or one of its subclasses to be excluded.
For the non-prefix part of the method name to be renamed to match the new name of a field, all of the following must be true:
  • All the above conditions for exclusion of the method name's prefix are met.
  • The field's original name equals the non-prefix and non-suffix part of the method's name.
  • The field is contained in
    • the class containing the matching method or
    • the hierarchy of the class containing the matching method.
exclude *.* get<link>() and //Exclude the "get" prefix in all method names starting with "get" that take no parameters
        *.* set<link>(java.lang.String); //Exclude "set" prefix in all methods starting with "set" which take a single String parameter

Class suffix exclude parameters

If a class matches a class suffix exclude parameter
  • its specified suffix is excluded from being renamed
  • if present, its specified prefix is excluded from being renamed
  • if a class X can be found that has an unqualified name matching the non-prefix and non-suffix part of the matching class's name then the non-prefix and non-suffix part of the matching class's name will be renamed to the new name of the class X.
For example, for a class suffix exclude parameter _<link>_Skel the prefix is _ and the suffix is _Skel. A hypothetical class named _Class1_Skel matches the parameter so the prefix and suffix parts of the name will be retained. The non-prefix and non-suffix part of the matching class name _Class1_Skel is "Class1". If there is a class in the same package or in a package matching any of the search clause packages named Class1 and if, when obfuscating, Class1 is renamed to abc then the class _Class1_Skel will be renamed to _abc_Skel.

The class suffix exclude parameter is useful for situations in the:
  • RMI (e.g. the _Stub and _Skel suffixes) and
  • Java Beans (e.g. the BeanInfo and Customizer suffixes) scenarios.

Put informally (with mandatory components in bold), the syntax is:
<classAnnotations> <packageQualifiers>.<prefix><link><suffix> <extendsClause> <implementsClause> <searchClause>;

For the class suffix of a class to be excluded, all of the following must be true:
  • Its annotations must match any specified annotations.
  • The class's package qualifiers must match any specified package exclude parameter component (see Package exclude parameters). If there is no package exclude parameter component then the class must be in the default package.
  • If a prefix is present then class's unqualified name must start with the specified prefix.
  • The class's unqualified name must end with the specified suffix.
  • If the parameter has an extends clause then the class must be a subclass of the specified class
  • If the parameter has an implements clause then the class must directly or indirectly implement all of the specified interfaces
For the non-prefix and non-suffix part of the class name to be renamed to match that of another class, all of the following must be true:
  • All the above conditions for exclusion of the class name's suffix are met.
  • The other class's original name equals the non-prefix and non-suffix part of the class's name.
  • The other class is contained in
    • the same package as the class or
    • a package that matches one of the packages specified in the search path.
exclude *._<link>_Skel and //Exclude the "_" prefix and the "_Skel" suffix in all classes 
                           //with unqualified names starting with "_" and ending with "_Skel"                        
        <link>BeanInfo search pack1.*, pack2 and 
                           //Exclude the "BeanInfo" suffix in all classes that end with it
                           //that are in the default package. Search packages matching
                           //"pack1.*" or "pack2" for a class with an original name
                           //matching the non-suffix part of the class name.
        pack1.<link>X implements pack2.Class2;   
                           //Exclude the "X" suffix in all classes that end with it
                           //that are in "pack1" and implement "pack2.Class".

Syntax

"exclude" excludeParameter ("and" excludeParameter)* ";"

annotationSpecifier ::= ("@" [packageExcludeParameter] nameSpecifier) | annotationSpecifierAndList

annotationSpecifierAndList ::= ["!"] "(" annotationSpecifierOrList ("&&" annotationSpecifierOrList)* ")"

annotationSpecifierOrList ::= annotationSpecifier ("||" annotationSpecifier)*

classExcludeParameter ::=
   [annotationSpecifier] [["!"] "public" | "package"]
   [["!"] "abstract"] [["!"] "final"] [["!"] "interface"] [["!"] "synthetic"] [["!"] "enum"] [["!"] "annotation"]
   ["\"" archiveQualifier "\"" "!"] [packageExcludeParameter ["."] ["^"]] nameSpecifier ["^"] ["+"] [containingClause]
   [extendsClause] [implementsClause]

classSuffixExcludeParameter ::=
   [annotationSpecifier] [packageExcludeParameter] wildcardName "<link>" name [extendsClause] [implementsClause]
   [searchClause]

containingClause ::= "containing" "{" "memberAndList" "}"

excludeParameter ::= packageExcludeParameter |
classExcludeParameter |
fieldExcludeParameter |
methodExcludeParameter |
methodPrefixExcludeParameter |
classSuffixExcludeParameter

extendsClause ::= "extends" [annotationSpecifier] wildcardClassName

fieldExcludeParameter ::=
   classExcludeParameter [annotationSpecifier] [["!"] "public" | "protected"| "package"| "private"]
   [["!"] "static"] [["!"] "final"] [["!"] "transient"] [["!"] "volatile"] [["!"] "synthetic"] [["!"] "enum"]
   [type] nameSpecifier

fullyQualifiedClassName ::= name ("." name)*

implementsClause ::= "implements" [annotationSpecifier] wildcardClassName ("," [annotationSpecifier] wildcardClassName)*

methodExcludeParameter ::=
   classExcludeParameter [annotationSpecifier] [["!"] "public" | "protected"| "package"| "private"]
   [["!"] "abstract"] [["!"] "static"] [["!"] "final"] [["!"] "native"] [["!"] "synchronized"] [["!"] "synthetic"] [["!"] "bridge"]
   nameSpecifier "(" [ "*" | (parameter ("," parameter)*)] ")" ["throws" wildcardClassName] ["+signatureClasses"]

methodPrefixExcludeParameter ::=
   classExcludeParameter [annotationSpecifier] [["!"] "public" | "protected"| "package"| "private"]
   [["!"] "abstract"] [["!"] "static"] [["!"] "final"][["!"] "native"] [["!"] "synchronized"]
   name "<link>" "(" [ "*" | (parameter ("," parameter)*)] ")" ["throws" wildcardClassName]

memberAndList ::= ["!"] "(" memberOrList ("&&" memberOrList)* ")"

memberOrList ::= memberSpecifier ("||" memberSpecifier)*

memberSpecifier ::= fieldExcludeParameter | methodExcludeParameter

nameAndList ::= ["!"] "(" nameOrList ("&&" nameOrList)* ")"

name ::= (["0"-"9","a"-"z","A"-"Z","$","_"])+
   i.e. a Java identifer (e.g. a package, class, field or method name) with no wildcards allowed

nameOrList ::= nameSpecifier ("||" nameSpecifier)*

nameSpecifier ::= wildcardName | nameAndList

packageExcludeParameter ::= packageName | packageNameAndList

packageName ::= wildcardName ("." wildcardName)* "."
   NB: the final "." is part of the package name

packageNameAndList ::= ["!"] "(" packageNameOrList ("&&" packageNameOrList)* ")"

packageNameOrList ::= packageExcludeParameter ("||" packageExcludeParameter)*

parameter ::= [annotationSpecifier] ("*" | "?" | type)

searchClause ::= "search" packageName ("," packageName)*

type ::=
   ("byte" | "short" | "char" | "int" | "long" | "float" | "double"| "boolean" |
   fullyQualifiedClassName) ("[]")*

wildcardClassName ::= wildcardName ("." wildcardName)*

wildcardName ::= (["*","0"-"9","a"-"z","A"-"Z","$","_"])+
   i.e. a Java identifer (e.g. a package, class, field or method name) with the "*" wildcard allowed
Where archiveQualifier is a relative or absolute archive path name with the "*" wildcard allowed. E.g. "/lib/*.jar" or "myJar0.jar"
ZKM Script removeMethodCalls statement The ZKM Script Language ZKM Script unexclude statement
Zelix KlassMaster - Java Obfuscator