Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-8863

Groovy compiler doesn't generate InnerClasses attribute for nested class names mentioned in the class file

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.5.3
    • 4.0.4
    • Compiler
    • None

    Description

      It seems that the Groovy compiler does not generate correct InnerClasses attributes when Groovy code uses inner classes, even if those are Java classes compiled separately.

      For example, the following code:

      class Test {
          void f(Thread.State t) {}
      }

      (where java.lang.Thread.State is just an example nested class from JDK) will compile by Groovy to a class file Test.class which has no InnerClasses attribute. If compiled by Java though, it has the following:

      InnerClasses:
          public static final #10= #9 of #18; //State=class java/lang/Thread$State of class java/lang/Thread

      While I couldn't find a statement requiring this attribute to be present for all nested classes mentioned in the class file in the JVMS, I believe §4.7.6 sort of hints at that with the following:

      If the constant pool of a class or interface C contains at least one CONSTANT_Class_info entry (§4.4.1) which represents a class or interface that is not a member of a package, then there must be exactly one InnerClasses attribute in the attributes table of the ClassFile structure for C.

      In this case, there's certainly a CONSTANT_Class_info entry in the Groovy-generated class file which represents a non-top-level class, but the InnerClasses attribute is missing, so I'd say this violates the spec.

      We've met this issue when refactoring the internal implementation of class file reader in the Kotlin compiler, where we got rid of the heuristic that calculated the full class name by replacing dollar characters with dots, and started to rely only on the InnerClasses attribute to correctly map JVM names to the "real" names of classes. This looked correct because at least class files generated by javac always have InnerClasses for all nested classes mentioned in the class file (not only in signatures, even those used only in method bodies!). However, for Groovy this turned out not to be the case. We'll probably workaround this problem somehow, for example by attempting to determine the class name twice, first by InnerClasses attribute values and second, by the aforementioned heuristic, but it'll be nice to get rid of the latter code in the future once this issue is fixed.

      Attachments

        Issue Links

          Activity

            People

              emilles Eric Milles
              udalov Alexander Udalov
              Votes:
              1 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: