Type variable information is not always maintained for anonymous classes
Sergei Ustimenko
merkel05 at gmail.com
Wed Dec 19 20:50:51 UTC 2018
Hi,
Coming back to the topic, I feel like I need some help.
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> 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>> 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>>> 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