Nester
Nester is a tool to patch inner class attributes in Java class files. It takes in a Nests data file and applies those patches to a jar file.
Inner Classes
Inner classes are classes that are defined inside other classes or methods. There are three types of inner classes: nested classes, local classes, and anonymous classes. Each type has its own uses, and a different relationship with its outer class or method.
Nested Classes
A nested class is a class declared inside another class.
public class Outer { ... public class Inner { ... } }
Nested classes can be static or non-static.
- A static nested class can access static members of its outer class, and vice versa, even if those members are private.
- A non-static nested class can access both static members and instance members of its outer class, and vice versa, even if those members are private.
Local Classes
A local class a class declared inside a method.
public class Outer { .... public void outer() { ... class Inner { ... } } }
A local class can access both static and instance members from its outer class, as well as local variables from the scope in which it is declared in its outer method.
Anonymous Classes
An anonymous class is a class declared and instantiated at the same time.
public class Outer { ... public void outer() { ... Runnable task = new Runnable() { ... } } }
An anonymous class can access both static and instance members from its outer class, as well as local variables from the scope in which it is declared in its outer method.
Special Classes
The Java compiler may generate special classes for some of the language's features. These synthetic classes are normally invisible.
- Switch statements are compiled to classes with enum value tables.
- A completely empty class may be generated and passed between multiple nested classes and their outer class to enforce the contract for access between them.
Inner Class Names
While the JVM specification does not enforce any naming scheme for inner classes, there is a convention for each type of inner class.
- Names for nested classes are typically composed of the outer class name and the inner name of the nested class. For example, a nested class with outer class name
com/example/Outer
and inner nameInner
typically has the namecom/example/Outer$Inner
. - Names for local classes are typically composed of the outer class name, the inner name of the inner class, and a number that counts up for each local class in the top-level outer class. For example, the second local class in some top-level class, with outer class name
com/example/Outer
and inner nameInner
typically has the namecom/example/Outer$2Inner
. - Names for anonymous classes are typically composed of the outer class name and a number that counts up for each anonymous class in the outer class. For example, the third anonymous class in outer class
com/example/Outer
typically has the namecom/example/Outer$3
.
Inner Class Attributes
Inner class attributes describe the relationship between inner classes and their outer classes or methods. Obfuscators such as ProGuard may remove them to shrink the jar file size. This is generally not a problem, since these attributes do not affect the runtime behavior of a Java application. However, they do make a difference at compile time.
Interactions with inner classes will not work properly if the inner class attributes are missing. Access between non-static nested classes and their outer classes will be broken, anonymous classes will be accessible when they should not be, and references to nested classes will not work.
On top of the compile time issues, decompiler results will be significantly worse for jars where the inner class attributes are not present. Local and anonymous classes will not appear inside their outer classes and methods, and member access between nested classes and their outer classes may appear as references to methods that do not exist.
The InnerClasses Attribute
The InnerClasses
attribute of a class contains entries for all inner classes referenced by that class. Each entry has four values:
inner class name
: the internal name of the inner classouter class name
: the internal name of the outer classinner name
: the simple name of the inner class (i.e. the name as declared in the source)inner class access
: the access modifier flags of the inner class
The outer class name
is empty for anonymous and local classes.
The inner name
value is empty for anonymous classes.
The EnclosingMethod Attribute
The EnclosingMethod
attribute of a class describes the outer class and method of an inner class. It has three values:
enclosing class name
: the internal name of the enclosing classenclosing method name
: the name of the enclosing methodenclosing method descriptor
: the type descriptor of the enclosing method
This attribute is only present for local and anonymous classes.
The enclosing method name
and enclosing method descriptor
values are empty for anonymous classes that are declared in in-line initializers for fields.
Nester
Nester patches inner class attributes in a jar using a Nests data file. It has the following features:
- Adding inner class attributes to existing classes.
- Remapping inner classes to fit the convention for inner class names.
- Generating new classes if outer classes specified in the Nests file do not exist.