Solved (Re: A pure Java example with reflective access behaving differently with invokeWithArguments() compared to core reflection's invoke() (Re: Strange observation: MethodHandle.invokeWithArguments() would not work, whereas Method.invoke() would with the very same arguments

Rony G. Flatscher Rony.Flatscher at wu.ac.at
Mon Jun 11 14:37:15 UTC 2018


Hi Peter,

once more: thank you very much for your explanations, efforts and patience! :)

On 10.06.2018 17:04, Peter Levart wrote:
> I showed you some code samples in Java language, so I had to explain what java compiler is doing
> too, for you to fully understand what's going on. You see, when using Java and
> HM.invokeWithArguments(), conversions (varargs included) are taking place at two levels. The 1st
> conversion is performed by javac generated bytecode (when invoking .invokeWithArguments, which is
> a varargs method) and the 2nd is the conversion performed by the HM.invokeWithArguments() method
> itself when it invokes the target method. The 1st is specified by JLS, while the 2nd is specified
> in the javadoc of .invokeWithArguments.
>
> If we skip the 1st conversion, since you probably know what compiler is doing, you still have to
> be aware of the 2nd conversion, performed by MH.invokeWithArguments() (and MH.invoke()). First
> thing you have to know is the following:
>
> /Method handles produced by lookups or constant loads from methods or constructors with the
> variable arity modifier bit (0x0080) have a corresponding variable arity, as if they were defined
> with the help of asVarargsCollector.//
> /
> This part does not mention the MethodHandles.Lookup.unreflect(Method) way of producing
> MethodHandle(s), but its all the same. You have to be aware that some method handles returned to
> you have a special property: they are varargs collectors. When invoking those methods, they accept
> any number of trailing positional arguments and collect them into an array argument.
>
> This does not happen when you invoke such methods using reflection.
>
> So if you want HM.invokeWithArguments() to behave the same as Method.invoke(), you have to
> transform the method handles obtained from lookup / unreflect with MH.asFixedArity() method. If
> the method handle is already a fixed arity method handle, this method will just return it, else it
> will return the equivalent method handle that doesn't perform collection of trailing positional
> arguments into an array argument. Using MH.asFixedArity() on each and every method handle you
> obtain by unreflect should give you the same behavior of MH.invokeWithArguments() as using
> Method.invoke().
Indeed, this seems to solve the problem, which is really great as this problem can be put to rest
and it makes it safe to use MH invocations in the bridge from Java 8 on!

Thank you *very* much again!
(And now, "after the fact" of your explanations I have become able to understand the cause of the
problem and its solution. I simply was not aware that by default a varargs collector would be
employed for the last (in this case single) argument for a varargs argument.)

---

Now, I would have another request in this context: are there any tutorials that would introduce one
into the world of MethodHandle(s) in the sort of "for dummies"? The reason I ask is as follows: in
the past years I have followed the introduction of MethodHandle(s) with Java 7 and from time to time
skimmed over articles demonstrating the basics of taking advantage of MH. Yet when starting to use
them for rewriting the reflective invocation part I encountered a world that is documented, but
maybe too briefly (and for MH experts). It took me quite a long time to learn about the most
important methods and how to employ them. (But obviously, there is too much I am still not aware of.)

My take is that probably a little bit of more documentation and/or brief tutorials that stress
different aspects of MH programming (for the uninitiated, newbies) would help considerably. Maybe
brief ("nutshell") tutorials each explaining and demonstrating the different kinds of MH methods
(what problem do they solve, how would one program a problem solution).

So if anyone could point to such brief tutorials/articles "for newbies/dummies" covering and
demonstrating all the MH methods, this would be really great!

---rony


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20180611/70719a7e/attachment.html>


More information about the mlvm-dev mailing list