Java.class file structure - InnerClasses attribute
Each CONSTANT_Class_info entry in the constant_pool table that represents a C class or interface that is not a member of a package must have exactly one corresponding entry in the class array.
The array of classes is a member of the InnerClasses attribute.
it is not a member of a class or interface (that is, if
a top-level class or interface (JLS §7.6) or a local class (JLS §14.3) or anonymous class (JLS §15.9.5)), the value of External_information_class shall be zero.
It seems to me that C could even be a top-level class (as said in the previous quote -
".. that is, if C is a top-level class ..."
but how is it possible that C would be a top-level class if the first quote says
"... a C class or interface that is not a member of a package ..."
Does "not package member" mean that the class must be nested correctly? Therefore, it cannot be a top-level class.
source to share
I think this is a good language-lawyer case. The first statement says that
Each CONSTANT_Class_info entry in the constant_pool table that represents a C class or interface that is not a member of the package must have exactly one corresponding entry in the class array.
However, it does not say that a top-level class is not allowed to have an entry in an array of classes.
Now why he will have a record I don't know. Perhaps this is for future extensibility. But the spec allows it, and it will be ignored by implementations because it is not really an inner / member class.
Thus, the statements are not technically contradictory.
source to share
Each class that participates in the internal relationship of a class to a given class must be represented in an attribute of the inner class of that class.
Let's say you have A, B and C and B is the inner class of A and C is the inner class B. Then the way it should work is that the attribute of the inner class has entries for A and B, B has entries for A, B, and C, and C has entries for B and C. At least the code that should work works that well, but the JVM only partially applies it.
Now another question is why this redundancy was chosen in the first place.
I suspect the security benefits are responsible for this. Originally, the attributes of the inner class were completely out of control, so you could create the Foo class and declare it to be the inner class of any other class, even system classes like java.lang.Object. But the developers feared that security decisions could be made based on interchangeable internal relationships between classes (i.e. Foo is an internal class of something in a Java package, so it must be trusted). Their solution was to require both classes to mention each other in their inner class attributes. So it is impossible to pretend to be the inner class of an existing class that doesn't know about you.
Of course, the checks seem to be broken because they only go in one direction. You can still create a Foo class and declare java.lang.Object to be an inner class of Foo. You can also do things like create a class Foo that claims to be an inner class. But when I searched, I couldn't find any real instances of security based on inner classes anyway, so this is probably a moot point.
source to share