You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Alexander Udalov (JIRA)" <ji...@apache.org> on 2018/10/29 18:40:00 UTC

[jira] [Created] (GROOVY-8863) Groovy compiler doesn't generate InnerClasses attribute for nested class names mentioned in the class file

Alexander Udalov created GROOVY-8863:
----------------------------------------

             Summary: Groovy compiler doesn't generate InnerClasses attribute for nested class names mentioned in the class file
                 Key: GROOVY-8863
                 URL: https://issues.apache.org/jira/browse/GROOVY-8863
             Project: Groovy
          Issue Type: Bug
          Components: Compiler
    Affects Versions: 2.5.3
            Reporter: Alexander Udalov


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|https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7.6] sort of hints at that with the following:
{quote}If the constant pool of a class or interface C contains at least one {{CONSTANT_Class_info}} entry ([§4.4.1|https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-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.
{quote}
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|https://github.com/JetBrains/kotlin/commit/9df02b236620e413ef70cea0d1d8ed93cd0b474e] 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|https://youtrack.jetbrains.com/issue/KT-27874] 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.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)