Type variable information is not always maintained for anonymous classes

David Holmes david.holmes at oracle.com
Tue Jan 1 23:14:17 UTC 2019


Hi Sergei,

On 20/12/2018 6:50 am, Sergei Ustimenko wrote:
> Hi,
> 
> Coming back to the topic, I feel like I need some help.

I can't really help. I agree with your analysis. We need to keep track 
of the scopes correctly even when one of them is implemented as a VM 
anonymous class!

David
-----

> Below is a stack trace so things would be easier to explain:
> 
> "main at 1" prio=5 tid=0x1 nid=NA runnable
>    java.lang.Thread.State: RUNNABLE
>        at 
> sun.reflect.generics.scope.ClassScope.computeEnclosingScope(ClassScope.java:51)
>        at 
> sun.reflect.generics.scope.AbstractScope.getEnclosingScope(AbstractScope.java:77)
>        at 
> sun.reflect.generics.scope.AbstractScope.lookup(AbstractScope.java:95)
>        at 
> sun.reflect.generics.factory.CoreReflectionFactory.findTypeVariable(CoreReflectionFactory.java:110)
>        at 
> sun.reflect.generics.visitor.Reifier.visitTypeVariableSignature(Reifier.java:165)
>        at 
> sun.reflect.generics.tree.TypeVariableSignature.accept(TypeVariableSignature.java:43)
>        at 
> sun.reflect.generics.visitor.Reifier.reifyTypeArguments(Reifier.java:68)
>        at 
> sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:138)
>        at 
> sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
>        at 
> sun.reflect.generics.repository.ClassRepository.computeSuperclass(ClassRepository.java:104)
>        at 
> sun.reflect.generics.repository.ClassRepository.getSuperclass(ClassRepository.java:86)
>        at java.lang.Class.getGenericSuperclass(Class.java:955)
>        at Bug8213465.printIt(Bug8213465.java:15)
>        at Bug8213465.lambda$main$0(Bug8213465.java:8)
>        at Bug8213465$$Lambda$1.1229416514.run(Unknown Source:-1)
>        at Bug8213465.main(Bug8213465.java:9)
> 
> ClassScope in our case is created by the CoreReflectionFactory, when
> Class#getGenericSuperclass being called. Creation is triggered, when type
> variable lookup happens. Class Scope in our case is the scope of
> anonymous class. Since type variable is not defined on the anonymous
> class, lookup is delegated to the enclosing scope, which is the lambda's
> scope i.e. MethodScope.
> 
> As you see, I have a breakpoint at the ClassScope.java:51 which is
> ```
> 
> Method m = receiver.getEnclosingMethod();
> 
> ```
> Lambda obviously doesn't declare the type variable => the next scope
> that would be queried is the lambda's enclosing scope which is the class
> scope. That ends up with the DummyScope and at Reifier.java:69
> a null value is being placed into the Type[0]. All the way down that
> results in the type variable being resolved to null.
> 
> The problem here is that type variable is declared at the method which
> encloses lambda, so that is the place where the problem comes in -
> we should somehow query the `main` method (in the example) for
> it's type variable declaration.
> 
> I've tried to query it with some sort of stack walking. That I've tried at
> the ClassScope:51, so simply check if the method returned by the
> `getEnclosingMethod()` is synthetic, then use stack walker to baktrack.
> That is not working, since I there's no way to retain method
> arguments. Thus it wouldn't work for overloaded methods.
> 
> I've searched through the `Method` class and found `Method#root`
> property. Could you please shine a light on it? Maybe we could harness
> it for lambdas to find the lambda's enclosing method?
> 
> The other way I thought of is whether it make sense to add a new
> `Method#getEnclosingMethod` method, that in case of synthetic
> methods would return non-null method, which encloses it.
> 
> So it seems a bit cumbersome, but I really need a bit of advise here.
> If anyone wants to participate and has some time, your thoughts would
> be of the great value!
> 
> Thanks,
> Sergei
> 
> 
> On Tue, 11 Dec 2018 at 08:20, David Holmes <david.holmes at oracle.com 
> <mailto:david.holmes at oracle.com>> wrote:
> 
>     On 11/12/2018 4:27 pm, Sergei Ustimenko wrote:
>      > Hi David,
>      >
>      > Thanks for checking it, I'll continue working on it then.
>      > Just wondering if you have any thoughts on how fix would
>      > look like.
> 
>     No. I tried tracking through the Java code to see how this works but
>     the
>     path is too long and convoluted :( The information is correct in the
>     classfile, but somewhere along the way the nature of the enclosing type
>     affects the answer that is produced. See ParameterizedTypeImpl and how
>     it gets created by CoreReflectionFactory.
> 
>     BTW as far as I can see it is not allowed for that method to produce
>     null: the type array can be empty, or creating it can throw an
>     exception, but otherwise the entries cannot be null.
> 
>     Cheers,
>     David
> 
>      > Regards,
>      > Sergei
>      >
>      > On Tue, 11 Dec 2018 at 02:34, David Holmes
>     <david.holmes at oracle.com <mailto:david.holmes at oracle.com>
>      > <mailto:david.holmes at oracle.com
>     <mailto:david.holmes at oracle.com>>> wrote:
>      >
>      >     Hi Sergey,
>      >
>      >     I've had a look and I don't think this issue is relevant to
>      >     JDK-8171335.
>      >     The problem seems to occur when you have a "hidden" enclosing
>     context
>      >     for the type, and that doesn't change with JDK-8171335.
>      >
>      >     David
>      >
>      >     On 9/12/2018 6:04 am, Sergey wrote:
>      >      > Hi David,
>      >      >
>      >      > Thanks for pointing that out!
>      >      >
>      >      >  >We need to see how this example work in that case.
>      >      >
>      >      > I guess anyone involved could have straight away two
>      >      > test cases: one from the bug itself and another from the
>      >      > observation above.
>      >      >
>      >      > In any case. looking forward for that being fixed. I would
>      >      > also be happy to be able to help with anything if needed.
>      >      >
>      >      > Thanks and regards,
>      >      > Sergei
>      >      >
>      >      > On Sat, 8 Dec 2018 at 12:03, David Holmes
>      >     <david.holmes at oracle.com <mailto:david.holmes at oracle.com>
>     <mailto:david.holmes at oracle.com <mailto:david.holmes at oracle.com>>
>      >      > <mailto:david.holmes at oracle.com
>     <mailto:david.holmes at oracle.com>
>      >     <mailto:david.holmes at oracle.com
>     <mailto:david.holmes at oracle.com>>>> wrote:
>      >      >
>      >      >     Hi Sergey,
>      >      >
>      >      >     Just FYI we're in the process of moving away from
>     using anonymous
>      >      >     classes for lambda's to using an extended
>     Lookup.defineClass
>      >     API - see:
>      >      >
>      >      > https://bugs.openjdk.java.net/browse/JDK-8171335
>      >      >
>      >      >     this is being done under Project Valhalla, with
>     current work
>      >     in the
>      >      >     nestmates branch.
>      >      >
>      >      >     We need to see how this example work in that case.
>      >      >
>      >      >     Cheers,
>      >      >     David
>      >
> 


More information about the core-libs-dev mailing list