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
Sun Mar 11 19:22:45 UTC 2018


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

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


More information about the mlvm-dev mailing list