Search code examples
javainvocationinvokedynamicmethodhandle

MethodHandle InvokeExact parameter


I am confused by method parameters for method handles. I first build a guardwithtest method handle as shown below:

public class App 
{
    public static void trueTarget(String str, String own, String t){
        System.out.println("This is true target "+str+" "+own + " "+t);
    }

    public static void falseTarget(String str, String own, String t){
        System.out.println("This is false target " + str+"  "+own +" "+t);
    }

    public static void main( String[] args ) throws Throwable
    {
        MethodHandle test = MethodHandles.publicLookup().findVirtual(String.class, "startsWith", 
                MethodType.methodType(boolean.class, String.class));

        System.out.println((boolean)test.invokeExact("result", "res"));

        MethodHandle target = MethodHandles.lookup().findStatic(App.class, "trueTarget", MethodType.methodType(void.class, String.class, String.class, String.class));
        MethodHandle fallback = MethodHandles.lookup().findStatic(App.class, "falseTarget", MethodType.methodType(void.class, String.class, String.class, String.class));

        MethodHandle gwd = MethodHandles.guardWithTest(test, target, fallback);

        gwd.invokeExact("result", "data", "sijie");

    }
}

The problem for me is that how parameters are passed to three method handles: test, trueTarget and faliover. 1, The first parameter for invokeExact "result" is passed to the test guard as receiver, and the 2nd parameter "data" is passed to startWith:

      String.startsWith(String)
      "result"          "data"  

But the these three parameters are passed to the falseTarget as:

      falseTarget(String str, String own, String t)
                        "result"      "data"     "sijie"

So, what's the rule for parameters passing and how do they match to the methods referenced by a method handle?


Solution

  • This appears in the Javadoc of findVirtual

    When called, the handle will treat the first argument as a receiver and dispatch on the receiver's type to determine which method implementation to enter.

    It's exactly as you described it. A static method does not have a receiver and therefore all arguments to invokeExact are considered arguments to the method.