Krab
Krab

Reputation: 6756

Java .class file structure - The InnerClasses attribute

http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.6

Every CONSTANT_Class_info entry in the constant_pool table which represents a class or interface C that is not a package member must have exactly one corresponding entry in the classes array.

The classes array is member of the InnerClasses attribute.

outer_class_info_index

If C is not a member of a class or an interface (that is, if C is a top-level class or interface (JLS §7.6) or a local class (JLS §14.3) or an anonymous class (JLS §15.9.5)), the value of the outer_class_info_index item must be zero.

QUESTION:

It looks for me that C could be even top level class (as the previous quotation says -

"..that is, if C is a top-level class..."

but how it is possible that the C will be top level class, if the first quotation says

"...class or interface C that is not a package member..."

"not package member" means that the class must be nested right? So it can't be top level class.

Upvotes: 3

Views: 491

Answers (2)

Antimony
Antimony

Reputation: 39451

Every class that is involved in an inner class relationship with a given class should be represented in that class's inner class attribute.

Say, you have A, B, and C, with B an inner class of A, and C an inner class of B. Then the way it's supposed to work is that A's inner class attribute has entries for A and B, B has entries for A, B, and C, and C has entries for B and C. At least this is how well behaved code should work, but the JVM only partially enforces it.

Now the other question is why this redundancy was chosen in the first place.

I suspect that the reason for this is perceived security benefits. Originally, inner class attributes were completely unchecked, so you could create a class Foo, and declare it to be an inner class of any other class, even system classes like java.lang.Object. But the developers were worried that security decisions might be made on the basis of spoofable inner class relationships (i.e. Foo is an inner class of something in the Java package, so it must be trusted). Their solution was to require that both classes mention each other in their inner classes attributes. That way it's impossible to pretend to be the inner class of an existing class that doesn't know about you.

Of course, the checks are kind of broken because they only go in one direction. You can still create a class Foo and claim that java.lang.Object is an inner class of Foo. You can also do stuff like create a class Foo which claims to be an inner class of itself. But when I searched, I couldn't find any actual instances of security based on inner classes anyway, so it's probably a moot point.

Upvotes: 0

Erwin Bolwidt
Erwin Bolwidt

Reputation: 31279

I think this is a good language-lawyering case. The first statement says that

Every CONSTANT_Class_info entry in the constant_pool table which represents a class or interface C that is not a package member must have exactly one corresponding entry in the classes array.

However, it doesn't say that a top-level class is not allowed to have an entry in the classes array.

Now why it would have an entry there, I don't know. Perhaps it is for future extensibility. But the spec allows it and it will be ignored by implementations because it's not really an inner/member class.

So the statements are not technically contradictory.

Upvotes: 2

Related Questions