Queries and patch for JDK-8034854: outer_class_info_index of synthetic class is not zero

Vicente-Arturo Romero-Zaldivar vicente.romero at oracle.com
Fri Feb 21 09:34:40 PST 2014

On 21/02/14 16:29, Jan Lahoda wrote:
> On 02/20/2014 10:06 PM, Alex Buckley wrote:
>> Interesting reasons. Does reuse of an existing top-level or anonymous
>> class choose from a pool of all classes (inc. user-defined ones) or only
>> synthetic classes?
> User-defined anonymous classes are reused for private constructor tags 
> if available, but, on a closer look, user-defined anonymous classes 
> don't seem to be reused in other cases. User-defined top-level classes 
> (if available) appear to be reused for targets <= 1.4 to hold the 
> desugared code for class literals.
>> I'm still not clear if "one class is synthesized per top-level type"
>> means "one member class" or "one anonymous class". I guess the
> Internally, they look somewhat like a member class with an empty name 
> ("anonymous member class"). But I don't think the internal 
> representation should affect the content of the attributes in this case.
>> ill-formed answer currently given by javac is "one member-anonymous
>> class", because the non-zero outer_class_info_index implies it's a
>> member class while the zero inner_name_index implies it's an anonymous
>> class - yuk. I recommend making them truly anonymous.
> Thanks.
> A webrev that updates tests according to comments received so far:
> http://cr.openjdk.java.net/~jlahoda/8034854/webrev.01/

Hi Jan,

I would modify the proposed test by including all the cases for which 
javac generates synthetic classes, also it would be preferable if the 
test is included in just one file.


> Jan
>> Alex
>> On 2/20/2014 12:34 PM, Jan Lahoda wrote:
>>> As far as I was able to determine, these are the cases where and why 
>>> the
>>> auxiliary classes are generated/used:
>>> -as tags for access constructors for private constructors. An existing
>>> anonymous innerclass is reused as a tag, if available, otherwise at 
>>> most
>>> one class is synthesized per top-level type.
>>> -for target levels whose ldc instruction does not support references to
>>> classes, desugared code for class literals (a "getter" and cache for 
>>> the
>>> Class objects) is placed into a "cache" class. Depending on the
>>> circumstances, a top-level class or an existing anonymous innerclass is
>>> reused if possible, otherwise at most one class is synthesized per
>>> top-level type.
>>> -for switch-over-enum, a lazy map between enum constants and 
>>> ordinals is
>>> placed into a cache class. An existing anonymous innerclass is reused,
>>> if available, otherwise at most one class is synthesized per top-level
>>> type.
>>> -for interfaces, to hold their assertions enabled status. At most one
>>> class is synthesized per top-level type.
>>> Jan
>>> On 02/20/2014 08:14 PM, Alex Buckley wrote:
>>>> It would make sense to consider the full range of reasons why these
>>>> auxiliary classes are generated. You indicated one reason - tags for
>>>> accessing private ctors - and it makes sense to generate a "true"
>>>> anonymous class there (outer_class_info_index=0, inner_name_index=0).
>>>> But perhaps other reasons would justify auxiliary classes with
>>>> meaningful "owners" - again, your word - and there it would be 
>>>> sensible
>>>> to consider them as member classes rather than anonymous classes.
>>>> Alex
>>>> On 2/20/2014 3:11 AM, Jan Lahoda wrote:
>>>>> Hi Alex,
>>>>> Thanks for the comments.
>>>>> I was briefly considering filling some inner_name for the synthetic
>>>>> classes, but using zeroing outer_class_info_index seemed somewhat
>>>>> cleaner, safer (no risk of name clashes or misinterpretation of the
>>>>> name) and simpler. But if generating an inner_name for the synthetic
>>>>> classes would be (strongly) preferred, I can investigate it.
>>>>> Jan
>>>>> On 02/19/2014 08:13 PM, Alex Buckley wrote:
>>>>>> Hi Jan,
>>>>>> The requirement that outer_class_info_index must agree with
>>>>>> inner_name_index w.r.t. an anonymous class was added in JVMS7
>>>>>> because we
>>>>>> saw class files where they disagreed and it simply made no sense. 
>>>>>> The
>>>>>> requirement was conditioned on 51.0 class files because we didn't 
>>>>>> want
>>>>>> to break pre-7 class files with insensible InnerClasses.
>>>>>> The auxiliary classes generated by javac appear to have a meaningful
>>>>>> "owner" - your word - so it would seem appropriate to have a 
>>>>>> non-zero
>>>>>> outer_class_info_index. Just generate a random name for
>>>>>> inner_name_index. (The 4.7.6 text assumes the "original simple name"
>>>>>> can
>>>>>> be derived from source code, but that's not applicable for synthetic
>>>>>> classes.) This change could reasonably affect all target levels, 
>>>>>> since
>>>>>> no-one should be relying on the value of inner_name_index for these
>>>>>> auxiliary classes.
>>>>>> OTOH, your proposal to represent the auxiliary classes as true
>>>>>> anonymous
>>>>>> classes in InnerClasses is attractive because it exposes even less
>>>>>> information than at present. This change could reasonably affect all
>>>>>> target levels too, since no-one should be relying on the value of
>>>>>> outer_class_info_index for these auxiliary classes.
>>>>>> Alex
>>>>>> On 2/19/2014 4:34 AM, Jan Lahoda wrote:
>>>>>>> Hello,
>>>>>>> I have a few questions about JDK-8034854 and a possible 
>>>>>>> patch/fix for
>>>>>>> it. The bug URL:
>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8034854
>>>>>>> The problem is that while JVMS 7, 4.7.6. (The InnerClasses 
>>>>>>> Attribute)
>>>>>>> mandates that:
>>>>>>>   If a class file has a version number that is greater than or
>>>>>>> equal to
>>>>>>>   51.0, and has an InnerClasses attribute in its attributes table,
>>>>>>> then
>>>>>>>   for all entries in the classes array of the InnerClasses 
>>>>>>> attribute,
>>>>>>>   the value of the outer_class_info_index item must be zero if the
>>>>>>> value
>>>>>>>   of the inner_name_index item is zero.
>>>>>>> javac in some cases produces non-zero "outer_class_info_index"
>>>>>>> even if
>>>>>>> "inner_name_index" is zero. This happens for synthetically 
>>>>>>> generated
>>>>>>> auxiliary classes. These classes are generated for a number of
>>>>>>> reasons,
>>>>>>> for example to be used as tags when accessing private constructors.
>>>>>>> The
>>>>>>> synthetic classes internally have an empty name, so the generated
>>>>>>> "inner_name_index" is zero, but their owner is a class, so they get
>>>>>>> the
>>>>>>> non-zero "outer_class_info_index".
>>>>>>> I've sketched out a simple fix for this problem, which ensures that
>>>>>>> "outer_class_info_index" is zero for classes that have empty name:
>>>>>>> http://cr.openjdk.java.net/~jlahoda/8034854/webrev.00/
>>>>>>> After this change, the generated synthetic classes look a lot like
>>>>>>> anonymous classes defined in an initializer of the given class
>>>>>>> (based on
>>>>>>> the InnerClasses attribute and the EnclosingMethod attribute). That
>>>>>>> seems reasonable to me.
>>>>>>> My questions are:
>>>>>>> -does the fix above make sense?
>>>>>>> -the change affects all target levels. It seems to me that the new
>>>>>>> behavior makes sense even for pre-7 classfiles, but I'll gladly 
>>>>>>> limit
>>>>>>> the new behavior to only some minimal target level if desired.
>>>>>>> Any comments welcome.
>>>>>>> Thanks,
>>>>>>>     Jan

More information about the compiler-dev mailing list