Lambda vs anon class optimization effect on CHA

Remi Forax forax at univ-mlv.fr
Thu Aug 11 09:45:48 UTC 2016


Aleksey, 
you should log a bug about that, CHA should only consider initialized classes.

Rémi


On August 10, 2016 9:02:22 PM GMT+02:00, Aleksey Shipilev <aleksey.shipilev at gmail.com> wrote:
>On 08/10/2016 04:28 PM, Vitaly Davidovich wrote:
>> public abstract class Foo {
>>     public static java.util.function.Supplier<Foo> call() {
>>         return () -> Confuser.INSTANCE;
>>     }
>> }
>> 
>> public final class Impl extends Foo {}
>> 
>> public final class Confuser extends Foo {
>>       public static final Confuser INSTANCE = new Confuser();
>> 
>> }
>
>I renamed "Null" to "Confuser" and "null()" to "call()" above.
>
>
>> Then CHA kicks in.  Keep in mind that the code I'm running never
>invokes
>> call() and only instantiates Impl, so the expectation is that
>Confuser would
>> not load (and disable the single impl CHA optimization).
>> 
>> My understanding was that the lambda in call() would have a bootstrap
>> method that invokes the lambda metafactory to actually bind the call
>to
>> the synthetic static method that's generated, which in turn actually
>> references Confuser.INSTANCE (and would cause the class to load). 
>However,
>> I'm clearly missing or misunderstanding something.
>> 
>> Would anyone be able to explain the above situation? Is that
>expected?
>> Let me know if you need more info.
>
>This has nothing to do with CHA per se. Your question boils down to why
>a dependent class is resolved earlier. AFAIU, "Confuser" class is
>getting loaded when we verify Foo class. JDK 9b128 with
>-Xlog:class*=debug prints this:
>
>[0.917s][info ][class,init       ] Start class verification for: Foo
>[0.917s][debug][class,resolve    ] Foo Foo Foo.java (verification)
>[0.942s][debug][class,resolve    ] Confuser Foo (super)
>[0.942s][debug][class,resolve    ] Foo Confuser Foo.java (verification)
>[0.942s][info ][class,init       ] End class verification for: Foo
>
>Running with -Xverify:none avoids resolving the Confuser class. Now,
>the
>question is why verifier triggers the class resolution.
>
>I would go on and speculate this happens because we verify the lambda
>body code, which happens to reside in the same Foo class:
>
>  private static Foo lambda$call$0();
>    descriptor: ()LFoo;
>    flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
>    Code:
>      stack=1, locals=0, args_size=0
>         0: getstatic     #3                  // Field
>Confuser.INSTANCE:LConfuser;
>         3: areturn
>      LineNumberTable:
>        line 3: 0
>
>We have to verify that Confuser is indeed a subclass of Foo here, so
>the
>value read from field is assignable to a return type, right?
>
>If we drop "extends Foo" from Confuser and make lambda return Object,
>then we don't resolve the class. If we make Confuser.INSTANCE the Foo
>type, not Confuser, we don't resolve the class either. If we replace
>lambda with an anonymous class, then the body is in a separate .class,
>and we do not resolve again.
>
>Ultimately, I think JVMS allows resolving the class before referencing
>it (in contrast with _initialization_, which should happen no earlier
>than a first reference at run time) -- like in the example above, to
>read class metadata to aid verification.
>
>I would venture to guess that we can wire up CHA to look at what
>classes
>have been _initialized_ rather than what classes were _resolved_, but
>there is no telling how much bugs would that expose.
>
>Thanks,
>-Aleksey

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/attachments/20160811/9ef26aa6/attachment.html>


More information about the hotspot-compiler-dev mailing list