Eager enum class initialization with enum switch

Remi Forax forax at univ-mlv.fr
Wed Feb 20 11:48:36 UTC 2019


yes !
we can also fix the fact that shuffling the enum constants is currently a non compatible change.

Tagir,
you can have one bootstrap method for all enums (somewhere in the JDK) given that it will be called with a Lookup that reference the enum class and you can not use a condy directly because the ldc instruction has to be in the same classfile (not the same compilation unit) as the constant pool that defines the condy.

Rémi

----- Mail original -----
> De: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
> À: "Tagir Valeev" <amaembo at gmail.com>, "Alex Buckley" <alex.buckley at oracle.com>
> Cc: "compiler-dev" <compiler-dev at openjdk.java.net>
> Envoyé: Mercredi 20 Février 2019 12:23:57
> Objet: Re: Eager enum class initialization with enum switch

> Hi Tagir,
> as you might know, we have plans to overhaul switch translation strategy:
> 
> https://mail.openjdk.java.net/pipermail/amber-spec-experts/2018-April/000522.html
> 
> Which, I think, should take care of fixing this particular issue. I
> think aiming for that plan is better than coming up with a point fix for
> this specific corner case.
> 
> Cheers
> Maurizio
> 
> 
> On 20/02/2019 05:24, Tagir Valeev wrote:
>> Hello, Alex!
>>
>> Thanks for reply. I filed an issue:
>> https://bugs.openjdk.java.net/browse/JDK-8219412
>>
>> It would be great were the lookup table created using condy bootstrap.
>> This would not only fix the reported problem,
>> but also reduce the amount of produced code. In particular, no
>> additional class file would be necessary:
>> bootstrap methods could be generated in the same class (one bootstrap
>> and one constant per enum; the same constant
>> could be reused for several switches over the same enum).
>>
>> With best regards,
>> Tagir Valeev
>>
>> On Wed, Feb 20, 2019 at 5:09 AM Alex Buckley <alex.buckley at oracle.com> wrote:
>>> On 2/16/2019 12:59 AM, Tagir Valeev wrote:
>>>> Consider the following program (Test.java):
>>>>
>>>> class Test {
>>>>     enum A{
>>>>       X;
>>>>       static { System.out.println("A is initialized!"); }
>>>>     }
>>>>     enum B{
>>>>       Y;
>>>>       static { System.out.println("B is initialized!"); }
>>>>     }
>>>>
>>>>     static void testA(A a) { switch(a) {} }
>>>>
>>>>     static void testB(B b) { switch(b) {} }
>>>>
>>>>     public static void main(String[] args) {
>>>>       testA(A.X);
>>>>     }
>>>> }
>>>>
>>>> When I compile it via javac and run it I see:
>>>> A is initialized!
>>>> B is initialized!
>>>>
>>>> Despite the fact that testB is never called, and no references to the
>>>> B enum actually used during the program execution. According to JLS
>>>> 12.4.1 B should not be initialized. Am I missing something?
>>> Using JDK 11, I agree that compiling and running Test produces the
>>> results you say.
>>>
>>> It's not valid to initialize the enum type B when no reference to B's
>>> constants or methods is made at run time. I vaguely recall prior
>>> discussions of this unfortunate aspect of javac's translation.
>>>
>>> I notice that the presence of the `testB(B)` method is what triggers
>>> javac's overly eager initialization of B. Without that method
>>> declaration, only "A is initialized!" is printed.
>>>
> >> Alex


More information about the compiler-dev mailing list