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
Fri Jun 8 10:07:53 UTC 2018
On 11.03.2018 20:22, Rony G. Flatscher wrote:
> Well, still trying to find out what the reason is, that core reflection's invoke behaves
> differently to MethodHandle's invokeWithArguments in one single case so far (using the method
> java.utli.Arrays.asList(...)).
>
> Here is a little Java program that excercises reflective access to
> "java.util.Arrays.asList(T... a)" using core reflection, i.e. "Method.invoke(Object obj,
> Object... args)" and "MethodHandle.invokeWithArguments(Object... arguments)":
>
> import java.util.*;
>
> import java.lang.reflect.*;
> import java.lang.invoke.*;
>
> class DemoAsListProblem
> {
> public static void main (String args[])
> {
> String arrNames[]=new String[] { "anne", "bert", "celine"};
> System.out.println("[1] (main) arrNames=\""+arrNames+"\", .toString()=\""+arrNames.toString()+"\"");
> List listNames=Arrays.asList(arrNames);
> System.out.println("[2] (main) after invoking Arrays.asList(arrNames), listNames=\""+listNames+"\"");
> System.out.println("\ninvoking testReflective() ...\n");
>
> testReflective();
> }
>
> public static void testReflective()
> {
> String arrNames[]=new String[] { "anne", "bert", "celine"};
> System.out.println("[3] (testReflective) arrNames=\""+arrNames+"\", .toString()=\""+arrNames.toString()+"\"");
>
> Method methAsList=null;
> List listNames=null;
> try {
> Class paramTypes[]=new Class[] { (new Object[0]).getClass() };
> methAsList=Arrays.class.getDeclaredMethod("asList", paramTypes);
> System.out.println("--- (core reflection) Method object asList: "+methAsList);
> System.out.println("\n--- (core reflection) now invoking Arrays.asList() via Method.invoke(...):");
>
> listNames=(List) methAsList.invoke( null, (Object[]) new Object[]{arrNames} ); // static method
> System.out.println("[4a] --- (CR) methAsList.invoke( null, (Object[]) new Object[]{arrNames} ) -> listNames=\""+listNames+"\"");
>
> listNames=(List) methAsList.invoke( null, (Object) new Object[]{arrNames} ); // static method
> System.out.println("[4b] --- (CR) methAsList.invoke( null, (Object) new Object[]{arrNames} ) -> listNames=\""+listNames+"\"");
>
> // "java.lang.IllegalArgumentException: wrong number of arguments":
> // listNames=(List) methAsList.invoke( null, (Object[]) arrNames ); // static method
> // System.out.println("[5a] --- (CR) methAsList.invoke( null, (Object[]) arrNames ) -> listNames=\""+listNames+"\"");
>
> listNames=(List) methAsList.invoke( null, (Object) arrNames ); // static method
> System.out.println("[5b] --- (CR) methAsList.invoke( null, (Object) arrNames ) -> listNames=\""+listNames+"\"");
> }
> catch (Throwable t)
> {
> System.err.println("oops #1: "+t);
> t.printStackTrace();
> System.exit(-1);
> }
>
> System.out.println("\n--- (MH) now invoking Arrays.asList() via MethodHandle.invokeWithArguments(...):");
> MethodHandles.Lookup lookup=MethodHandles.lookup();
> MethodHandle mh=null;
> try {
> mh=lookup.unreflect(methAsList);
> System.out.println("--- (MH) unreflected MethodHandle mh: "+mh);
>
> listNames=(List) mh.invokeWithArguments( (Object[]) new Object[]{arrNames} );
> System.out.println("[6a] --- (MH) mh.invokeWithArguments( (Object[]) new Object[]{arrNames} ) -> listNames=\""+listNames+"\"");
>
> listNames=(List) mh.invokeWithArguments( (Object) new Object[]{arrNames} );
> System.out.println("[6b] --- (MH) mh.invokeWithArguments( (Object) new Object[]{arrNames} ) -> listNames=\""+listNames+"\"");
>
> listNames=(List) mh.invokeWithArguments( (Object[]) arrNames );
> System.out.println("[7a] --- (MH) mh.invokeWithArguments( (Object[]) arrNames ) -> listNames=\""+listNames+"\"");
>
> listNames=(List) mh.invokeWithArguments( (Object) arrNames );
> System.out.println("[7b] --- (MH) mh.invokeWithArguments( (Object) arrNames ) -> listNames=\""+listNames+"\"");
>
> }
> catch (Throwable t)
> {
> System.err.println("oops #2: "+t);
> t.printStackTrace();
> System.exit(-2);
> }
> }
> }
>
> Compiling and running it under 9.0.4 yields the following output:
>
> [1] (main) arrNames="[Ljava.lang.String;@27ddd392", .toString()="[Ljava.lang.String;@27ddd392"
> [2] (main) after invoking Arrays.asList(arrNames), listNames="[anne, bert, celine]"
>
> invoking testReflective() ...
>
> [3] (testReflective) arrNames="[Ljava.lang.String;@2a18f23c", .toString()="[Ljava.lang.String;@2a18f23c"
> --- (core reflection) Method object asList: public static java.util.List java.util.Arrays.asList(java.lang.Object[])
>
> --- (core reflection) now invoking Arrays.asList() via Method.invoke(...):
> [4a] --- (CR) methAsList.invoke( null, (Object[]) new Object[]{arrNames} ) -> listNames="[anne, bert, celine]"
> [4b] --- (CR) methAsList.invoke( null, (Object) new Object[]{arrNames} ) -> listNames="[[Ljava.lang.String;@2a18f23c]"
> [5b] --- (CR) methAsList.invoke( null, (Object) arrNames ) -> listNames="[anne, bert, celine]"
>
> --- (MH) now invoking Arrays.asList() via MethodHandle.invokeWithArguments(...):
> --- (MH) unreflected MethodHandle mh: MethodHandle(Object[])List
> [6a] --- (MH) mh.invokeWithArguments( (Object[]) new Object[]{arrNames} ) -> listNames="[[Ljava.lang.String;@2a18f23c]"
> [6b] --- (MH) mh.invokeWithArguments( (Object) new Object[]{arrNames} ) -> listNames="[[Ljava.lang.Object;@13a57a3b]"
> [7a] --- (MH) mh.invokeWithArguments( (Object[]) arrNames ) -> listNames="[anne, bert, celine]"
> [7b] --- (MH) mh.invokeWithArguments( (Object) arrNames ) -> listNames="[[Ljava.lang.String;@2a18f23c]"
>
> So a String array is turned into a List using Arrays.asList(strArray). Doing it with core
> reflection yields different results to doing it with invokeWithArguments().
>
> I would have expected that [4a] and [6a] would behave the same.
>
> Using reflective invoke() and invokeWithArguments() has been working for my bridge for all the
> test units (using literally the same arguments in both cases) interchangeably, the one exception
> is Arrays.asList().
>
> Maybe I am not seeing the obvious (having done too much "close-up tests" for quite some time now).
> So any hint, insight, help would be really appreciated!
>
> ---rony
As a few months have gone by without any follow-ups, I have been wondering whether there is a
solution at all, if this is a problem rooted in the current implementation of MethodHandle methods
not being 100% compatible with reflective invoke (which may imply that one needs to stick to use
reflective invoke and forgo MethodHandle invokes for good).
---rony
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20180608/8eb3698d/attachment.html>
More information about the mlvm-dev
mailing list