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