Annotating lambda expressions

Remi Forax forax at univ-mlv.fr
Sun Jul 12 17:19:43 UTC 2015


On 07/12/2015 07:00 PM, Ron Pressler wrote:
> Yes, but only method definitions, not method bodies; that's a very big 
> difference.

yes, very true,
note that you only need to read the method body of methods that uses an 
invokedynamic.

while there is no way to know if a method uses an invokedynamic, without 
reading all the instructions but in the class:
- the constant pool will contain at least one 
CONSTANT_Invokedynamic_info entry,
- the attributes of the class will contain a BootstrapMethods attribute.

that said, both these info are not exposed publicly by ASM.

Rémi

[1] 
http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.10
[2] 
http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.23


>
>
> On Sat, Jul 11, 2015 at 4:39 PM, Remi Forax <forax at univ-mlv.fr 
> <mailto:forax at univ-mlv.fr>> wrote:
>
>     On 07/11/2015 03:02 PM, Ron Pressler wrote:
>>
>>     On Sat, Jul 11, 2015 at 3:59 PM, Ron Pressler
>>     <ron at paralleluniverse.co <mailto:ron at paralleluniverse.co>> wrote:
>>
>>         Thanks for the bootstrap argument tip! Will use that as a
>>         workaround.
>>
>>
>>     ... although it does require scanning the entire bytecode for the
>>     entire project (to find the indy callsites) rather than just
>>     looking for annotated methods...
>
>     ??
>     finding annotated methods requires to scan the entire project too ?
>
>
>>
>>     R
>
>     R
>
>>
>>         On Sat, Jul 11, 2015 at 12:26 PM, Remi Forax
>>         <forax at univ-mlv.fr <mailto:forax at univ-mlv.fr>> wrote:
>>
>>             On 07/11/2015 10:57 AM, Ron Pressler wrote:
>>>             That's a very nice idea (in fact, we can do
>>>             foo((@Special Runnable) ()->{...}), as well and get ASM
>>>             to invoke a nice  visitInsnAnnotation event), but it
>>>             doesn't help, as I have no way of finding the method
>>>             implementing the lambda by analyzing the bytecode.
>>
>>             The method corresponding to the body of the lambda is one
>>             arguments of the bootstrap method of invokedynamic.
>>               see
>>             http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html
>>             <http://cr.openjdk.java.net/%7Ebriangoetz/lambda/lambda-translation.html>
>>             (this translation scheme is not required to be used by
>>             compilers but in practice javac and ecj uses it and
>>             scalac will use it too)
>>
>>>             My suggestion says, "however the compiler chooses to
>>>             represent the lambda, please apply the annotation to the
>>>             implementing method, wherever it is". I think that the
>>>             language spec at least implicitly forces the compiler to
>>>             implement a lambda as a method /somewhere/ (as opposed
>>>             to, say, javac inlining the expression, as Kotlin does
>>>             with inline functions).
>>
>>             see above.
>>
>>>
>>>             The ability to attach introspectable metadata to a
>>>             lambda expression that then travels with it to the
>>>             implementing method -- wherever the compiler may choose
>>>             to place it -- is extremely useful, and trumps, IMO,
>>>             "purity" concerns re annotating expressions vs
>>>             declarations, (esp. since we've already established that
>>>             some expressions -- like cast and new -- are
>>>             annotatable, and rightly so).
>>
>>             cast and new are not annotatable, the type of a cast or a
>>             new are.
>>
>>>             Without this, we miss something important Java gives us,
>>>             which is the ability to attach metadata to a method
>>>             body. I fully understand the distinction that the
>>>             annotation is applied to the /declaration/ rather than
>>>             the body itself, but that doesn't take away from the
>>>             fact that a useful ability does not transfer to lambdas
>>>             while it could be easily done.
>>>
>>>             Ron
>>
>>             Rémi
>>
>>
>>>
>>>             On Sat, Jul 11, 2015 at 10:38 AM, Remi Forax
>>>             <forax at univ-mlv.fr <mailto:forax at univ-mlv.fr>> wrote:
>>>
>>>                 On 07/10/2015 11:41 PM, Ron Pressler wrote:
>>>>                 I see no problem with cast annotations not being
>>>>                 retrievable via straightforward reflection just as
>>>>                 I see no problem annotating the generated method
>>>>                 (which should always exist /somewhere/): in both
>>>>                 cases, those annotations are intended for use by
>>>>                 tools that analyze the entire project's
>>>>                 source/bytecode (e.g. for
>>>>                 typechecking/instrumentation) rather than by
>>>>                 specific reflective queries.
>>>>
>>>>                 What bothers me is that a capability that was
>>>>                 trivial with inner classes is now lost when using
>>>>                 lambdas.
>>>
>>>                 you can easily add a pattern recognizable by
>>>                 source/bytecode tools to do what you want,
>>>                 let suppose you have a static method like this:
>>>                   static <T> T annotate(Class<? extends Annotation>
>>>                 annotation, T lambda) { return lambda; }
>>>
>>>                 to annotate a lambda, your example can be written
>>>                 like this:
>>>                 foo(annotate(Special.class, () -> { ...}))
>>>
>>>                 in the bytecode it will be translated to something
>>>                 like this:
>>>                   ldc Special.class
>>>                 invokedynamic ()Runnable
>>>                 LambdaMetafactory + method handle ref on the lambda body
>>>                   invokestatic Bar.annotate(Class, Object)Object
>>>                   checkcast Runnable
>>>                 invokevirtual Baz.foo(Runnable)...
>>>
>>>                 which is easy to recognize.
>>>
>>>>
>>>>                 Ron Pressler
>>>>                 paralleluniverse.co <http://paralleluniverse.co/>
>>>>                 @puniverseco <https://twitter.com/puniverseco> on
>>>>                 Twitter
>>>
>>>                 Rémi
>>>
>>>
>>>>
>>>>                 On Fri, Jul 10, 2015 at 10:38 PM, Alex Buckley
>>>>                 <alex.buckley at oracle.com
>>>>                 <mailto:alex.buckley at oracle.com>> wrote:
>>>>
>>>>                     On 7/10/2015 2:31 AM, Maurizio Cimadamore wrote:
>>>>
>>>>                         On 10/07/15 09:43, Ron Pressler wrote:
>>>>
>>>>                             (Related to
>>>>                             http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009220.html)
>>>>
>>>>                             It is useful to add an annotation to a
>>>>                             lambda expression -- as in
>>>>                             foo(@Special () -> { ...}) -- which
>>>>                             will be applied to the static
>>>>                             method implementing the lambda (not to
>>>>                             the interface the lambda
>>>>                             implements). This would allow
>>>>                             instrumentation tools operating on
>>>>                             method implementations to handle
>>>>                             lambdas. So far, AFAICT, this is not
>>>>                             possible (or am I wrong?).
>>>>
>>>>                         This is not possible, currently - as Remi
>>>>                         said; you have annotations on
>>>>                         declarations (i.e. variable, classes,
>>>>                         methods) - you have annotation on
>>>>                         types (i.e. type of a cast, type argument,
>>>>                         etc.) - but you don't have
>>>>                         annotations on _expressions_.
>>>>                         I take it that, under the current
>>>>                         translation scheme, there seems to be
>>>>                         a plausible description for what should
>>>>                         happen when the lambda is
>>>>                         annotated; but what if the lambda is turned
>>>>                         into a method reference (by
>>>>                         some IDE refactoring, or human
>>>>                         intervention) ? In that case it is not
>>>>                         guaranteed that there would still be a
>>>>                         physical place where to put the
>>>>                         annotation (unless we tell the compiler to
>>>>                         'expand' all annotated method
>>>>                         references).
>>>>
>>>>
>>>>                     Yes, the problem with
>>>>                     annotations-on-expressions is not the language
>>>>                     grammar but the storage of the annotations in
>>>>                     the class file. With no standard way of
>>>>                     translating source expressions to bytecode,
>>>>                     there can be no standard API for retrieving
>>>>                     annotations-on-expressions from bytecode. More
>>>>                     broadly, there has never been a standard
>>>>                     reflective API capable of inspecting method bodies.
>>>>
>>>>                     This explains why JSR 308 stayed away from
>>>>                     annotations-on-expressions -- we were not in a
>>>>                     position to let them be read back. It was
>>>>                     already bad enough that some
>>>>                     annotations-on-types are stored in the class
>>>>                     file at the level of individual bytecodes (e.g.
>>>>                     an annotation on the type of a cast) so are not
>>>>                     retrievable by any standard reflective API.
>>>>
>>>>                     Alex
>>>>
>>>>
>>>
>>>
>>
>>
>>
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20150712/97c89221/attachment-0001.html>


More information about the compiler-dev mailing list