Zelix KlassMaster - Documentation
 

The trimExclude Statement

The ZKM Script trimExclude statement excludes the specified objects from being removed by the Zelix KlassMaster™ trim statement. Successive trimExclude statements have a cumulative effect. Once an exclusion has been set its effect can be

Note that the exclusion of a field or method is not enough in itself to prevent the field or method's containing class, and therefore the specified field or method, from being removed. The containing class must also be explicitly or implicitly excluded. A class, field or method is implicitly excluded if it is accessed by a method that
  1. has itself been explicitly or implicitly excluded and
  2. is contained in a class that has been explicitly or implicitly excluded.

So, for a standalone application, if the initial public static main(String[]) method is explicitly excluded along with its containing class then Zelix KlassMaster™ will implicitly exclude every class, field and method that is accessed directly or indirectly by the initial main method.

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

Examples and Explanation

trimExclude statement parameters may be loosely categorized into the following groups

Class exclude parameters

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

For a class to be excluded, all of the following must be true:
  • 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. 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.
trimExclude *          and         //exclude all classes in the default package
            *.Class1   and         //exclude all classes with the unqualified class name "Class1"
            public !final *.* and  //exclude all public non-final classes
            package abstract *.C*s extends pack1.Class1 and 
                           //exclude all "public abstract" classes that
                           //have an unqualified name matching "C*s" and extend "pack1.Class1".
            p*.*     and //exclude all classes in packages that start with the character "p"
            //exclude all classes with the unqualified class name "Class1" also exclude all fields and methods of those classes
            *.* Class2 + and 
            //exclude all classes with a name that start with "Class" except for "Class0" and "Class1"
            *.(Class* && !(Class0 || Class1)) and 
            "MyJar*.jar"!*.* and //exclude all classes contained in a JAR file with a name matching "MyJar*.jar"
            @*.MyAnnotation0 *.*;  //exclude all classes annotated which an annotation matching *.MyAnnotation0

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 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.
trimExclude *.* *                      and //Exclude all fields
            *.Class1 !transient int f* and //Exclude all non-transient "int" fields 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 class.
           *.* @*.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 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.

The trimExclude statement supports the special method names <init> and <clinit> which represent constructor and class initializer method names respectively. However, class initializers are automatically excluded from being trimmed in any case.
trimExclude *.* *(*)           and  //Exclude all methods
            *.* !static m*()   and  //Exclude all non-static methods taking no parameters with names matching "m*"
            *.* public <init>() and  //Exclude all public no argument constructors
            //Exclude all "native" methods. Also exclude the containing class.
            *.*^ native *(*)  and  
            *.* *(*) throws java.io.IOException and  //Exclude all methods that throw java.io.IOException. 
            //Exclude all "abstract" methods that  take a single String.
            *.* abstract *(java.lang.String) and 
            //Exclude all methods in pack1.Class1 along with the matching methods' return and parameter types
            pack1.Class1 *(*) +signatureClasses and 
            //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.
            *.* @*.MyAnnotation0 *(*);

Annotation exclude parameters

Put informally (with mandatory components in bold), the syntax is: @<className>

An annotation exclude parameter is fundamentally different from the Class exclude, Field exclude and Method exclude parameters discussed above. An annotation exclude parameter tells Zelix KlassMaster™ to not delete specified annotations appearing on classes, fields or methods that would otherwise be removed if the deleteAnnotationAttributes=true setting is specified on the trim statement.

trimExclude @pack0.AnnotationClass0 and //Don't remove any pack0.AnnotationClass0 annotations
            @*.MyAnnotation1; //Don't remove any annotations matching *.MyAnnotation1

Syntax

"trimExclude" excludeParameter ("and" excludeParameter)* ";"

annotationExclusionParameter ::= "@" wildcardClassName

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]

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

excludeParameter ::= classExcludeParameter |
fieldExcludeParameter |
methodExcludeParameter |
annotationExcludeParameter

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)*

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

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

memberSpecifier ::= fieldExcludeParameter | methodExcludeParameter

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

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

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

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

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)

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 open statement The ZKM Script Language ZKM Script trimUnexclude statement
Zelix KlassMaster - Java Obfuscator