7

I want to understand class files and inner/nested classes a bit better and I'm wondering about the following things:

  • Is the InnerClasses attribute used to refer tothe inner/nested classes in the ´containing´ class or is it used in the inner/nested classes to refer to the ‘container’ class?
  • Is the InnerClasses attribute in class files sufficient? E.g. Do inner/nested classes have to follow the name mangling with $ or is this just a convention?
  • Is there a way to make a class look like an inner/nested class to the JVM without setting the InnerClasses attribute and does this depend on the JLM vendor? (I remember hearing that IBM's implementation had less strict requirements in some parts.)
  • How much does the class loading mechanism of the JVM interact with Java reflection? Would it be possible to make the JVM disagree with the results from Java reflection?

I tried looking it up in the JVM specification but didn't find a description of the actual mechanism.

I only found this sentence in “The InnerClasses Attribute” remotely connected to my question:

The Java virtual machine does not currently check the consistency of the InnerClasses attribute with any class file actually representing a class or interface referenced by the attribute.

Seki
  • 11,135
  • 7
  • 46
  • 70
soc
  • 27,983
  • 20
  • 111
  • 215
  • 1
    After reading your comments below, I decided not to answer your question. I leave this comment here only to point out to you that your method of interaction below is perhaps not the best way to engage with this community when asking it for help. – philwb Feb 20 '12 at 17:57
  • Thank you for your kind words. I think the answer boiling down to “Why would you want to know that?” was patronizing and not appropriate in this community, but you may disagree. – soc Feb 20 '12 at 21:41

2 Answers2

2

A few additions to the previous answer:

Is the InnerClasses attribute used to store the contained inner/nested classes in the containing class or is it used in the inner/nested classes to refer to the ‘container’ class?

The bytecode of every compiled class is stored in a separate .class file. The the actual "inner classes" are not stored in that attribute. As the previous post pointed out, that attribute only points to classes that the compiler knew about when creating the bytecode.

Is the InnerClasses attribute in class files sufficient? E.g. Do inner/nested classes have to follow the name mangling with $ or is this just a convention?

Is there a way to make a class look like an inner/nested class to the JVM without setting the InnerClasses attribute and does this depend on the JLM vendor? (I remember hearing that IBM's implementation had less strict requirements in some parts.)

For both questions, I am not certain. But I think the concept of inner/nested classes is something that the Java language (and hence the Java compiler provides). In the bytecode, there should not be any difference between a class that was declared as a normal public class and some nested or inner class. You could easily try out how an given VM handles this like so:

  • Create a class with some nested and inner classes
  • Write a little program that tries to load and instantiate one of the inner classes through reflection from outside the scope of defining class. You must use reflection here, because the Java compiler will not allow you to instantiate a nested class that is not in scope! If you can successfully instantiate the class, that is evidence that internally the VM does not handle nested and normal classes differently.

How much does the class loading mechanism of the JVM interact with Java reflection? Would it be possible to make the JVM disagree with the results from Java reflection?

I don't understand this last question. Could you explain a bit more what you mean when you say the VM and reflection should disagree?

Community
  • 1
  • 1
Jochen
  • 2,277
  • 15
  • 22
  • Hi Jochen! 1) I was wondering about the direction of the `InnerClass` attribute, e. g. does it point from the inner class to the containing or the other way around? 2) I'm asking that because it seems to be underspecified in the spec. I'll try to test it as you recommended. – soc Feb 24 '12 at 16:36
  • 3) The JVM's "own" `ClassLoader` is implemented in native code, while the reflection functionality concerning classes is implemented in Java, largely with comparing and subStringing Strings. I wonder if it is possible to craft a file where the mechanism of the JVM disagrees with Java reflection. E. g. Java reflections says that `A$B` is an inner class of `A` while the JVM says no. – soc Feb 24 '12 at 16:38
  • I took a quick look and it appears that the InnerClasses attribute is set for BOTH. You can take a look at generated bytecode with Eclipses built in Class File Viewer (right-click on a .class file and select "Open with -> Class File Viewer"). The info written there tells you which is the outer and which is the inner class. So if someone (for example the class loader) would look, it could work it out from there. However, I suspect that this might be something that different compilers do differently. I have checked only with Eclipse/JDT. – Jochen Mar 04 '12 at 17:23
  • For that last question, I'm not sure, I'm not that good with reflection, but here is my take on it. 1) Any class loader initializes a number of internal data structures describing the class it is loading. That includes the meta classes that you can access through reflection (Class, Method, Constructor, etc.). 2) I'm sure you can construct a class loader that ignores the information about inner classes and thus would create a class that looks different from the one the default class loader would construct. – Jochen Mar 04 '12 at 17:33
  • HOWEVER, this is totally independent of reflection. Reflection will always tell you what the internal data structures contain, which is ultimately defined by the class loader used. As I don't know enough about this, I'd suggest you simply try to hack something that drops the InnerClasses attribute and then loads the class. The see if you can instantiate the inner class directly or not. – Jochen Mar 04 '12 at 17:35
  • Great! Thanks a lot. Could you put the information in your comments into your answer, so it is easier for other people to read? SO has sometimes the tendency to collapse the important comments. :-) – soc Mar 04 '12 at 18:05
1

I know that there is an inner class attribute in class files, but is this sufficient?

The InnerClasses attribute is in the byte code and it lists all the known inner classes of the outer class. This is not something you can use directly.

E.g. Do inner/nested classes have to follow the name mangling with $ or is this just a convention?

The compiler will follow this convention and you have no control over it.

Is there a way to make a class look like an inner/nested class to the JVM without setting the inner class attribute and does this depend on the JLM vendor? (I remember hearing that IBM's implementation had less strict requirements in some parts.)

You can create a class with the same name. YOu cna try that for yourself.

How much does the class loading mechanism of the JVM interact with Java reflection?

I don't believe the class loader uses reflection. However reflection may get its information from the same place the class loader does. I don't see why it would matter.

Would it be possible to make the JVM disagree with the results from Java reflection?

You can use reflection to corrupt the data in reflection based objects. Again, not sure why you would want to do this.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    Perhaps you could say what you more specifically want to know, like why you need to know this? – Peter Lawrey Nov 10 '11 at 16:25
  • I ask because I'm interested in how the different JVM's handle the things mentioned, considering there is no specified standard on how to do it. It's pure interest, that's why “why would you want to do that? Use `javac`!” doesn't really help me. – soc Nov 10 '11 at 18:23
  • @soc, I say "Use javac". Perhaps telling you not to worry about details you don't need to worry about is my idea of being helpful. ;) – Peter Lawrey Nov 10 '11 at 22:01
  • Its not just my option that its not important, even the spec states its a detail which it ignores. – Peter Lawrey Nov 10 '11 at 22:03
  • So what would you do if you intended to write a compiler generating Java bytecode? – soc Nov 11 '11 at 10:47
  • Rather than write it from scratch I would use the existing compiler which is open source and modify only the portions which are of interest. The problem with writing your compilers, or modifying an existing one is that they do get bug fixes from time to time and quickly become out of date. A more robust approach is to create a byte code manipulator which runs after the compiler to do whatever you need to do. This approach is used my many byte manipulation libraries and works with many versions of javac from different vendors. – Peter Lawrey Nov 11 '11 at 10:55
  • So you would write e. g. a Haskell-to-JVM compiler by modifying `javac`? – soc Nov 11 '11 at 10:58
  • 1
    Does Haskell have Inner Classes? Given InnerClasses is not checked, it wouldn't matter if it did and you set this or not. – Peter Lawrey Nov 11 '11 at 11:03
  • 1
    I am sure this intern was convinced he had done a good job and got things done too. http://thedailywtf.com/Articles/TwentyFour-Bits-Per-Intern.aspx I think you need to read this http://c2.com/xp/YouArentGonnaNeedIt.html or you may find you are wasting your time. – Peter Lawrey Nov 11 '11 at 11:21