DonÕt Use Inner Classes
The use of inner classes is convenient way to implement many features of Java. Inner classes have the benefits of unrestricted access to the enclosing class, including all variables and methods, public and private. It is also beneficial from a design point of view in order to decrease the number of classes in the developers perspective, it is not necessary to clutter your package with classes that are only a few lines long. One common use of Inner Classes is in the implementation of action listeners, these are small classes typically with only one method. It is beneficial to make the listener an inner class so you can access the variables of the containing class without restriction. This unrestrictive access can greatly enhance the utility of the listener. There are many other cases were an inner class is used, whether simplicityÕs sake or for design purposes they are a commonly used feature in Java.
However, the implementation of inner classes in the Java byte code causes a large problem. In Java 1.1 there were no inner classes, all classes had to be defined separately. Therefore all classes were compiled independently of one another and stored as such in their compiled form. In order to preserve backwards compatibility Java compilers have to compile inner classes into separate class files. Making inner classes no different from any other class in the package. This causes two major problems, the access that the class had to the enclosing classÕs variables is lost unless special accommodations are made, and also the classes are now accessible by any other class in the same package, not just the enclosing class. Because the compiler has separated the inner class from its enclosing type during compilation, any class in the package can now access all methods and variables in the inner class. This now places the inner class under the protection of the package scope, which is problematic due to a mix and match attack as discussed earlier. In addition the inner class is now separate from the enclosing class, the special access to the variables and methods of the enclosing class needs to be accounted for. In order to preserve this access the compiler uses a dangerous trick, it modifies the declared protection of the methods and variables in the enclosing class. No matter whether a variable or method was declared private, the compiler designates it as protected, so the former inner class still has access to the variable.[7] [6]
This vulnerability is especially dangerous because of its dual implications. Simply having an anonymous inner class, in any context, compromises all of code in both the inner class and the enclosing class. All variables and methods no matter their designation are made to be package accessible; due to the shortcomings of the package scope these variables are essentially publicly available. In addition all of the methods in the inner class are also package accessible, available to all classes in the package, not just the enclosing class. An example of such a security bug is as follows:
Class BankAccount {
private Integer accountNumber;
private AccountHolder personalInfo;
private AccountManager observer;
É
public BankAccount( Integer accountNumber, AccountHolder person){
this.accountNumber = accountNumber;
this.personalInfo = person;
personalInfo.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
observer.accountAction(prop, accountNumber);
}
});
}
}
This example would be compiled into two separate classes, making all of the variables of the class BankAccount accessible to any class in the package. In addition a class added to the package could call the propertyChange method and pass in their own PropertyChangeEvent and maliciously change the class invariant.