Search code examples
javamethodhandle

Local variables in MethodHandle


java.lang.invoke.MethodHandle and friends allow runtime code generation eligible for JIT via a series of combinators.

How can I create local variables in MethodHandles? Ideally, the method signature I want looks something like

MethodHandle withLocalVariable(
    Class<?> varClazz, Function<VarHandle, MethodHandle> usingVar)

though I'm not sure VarHandle is actually quite the right abstraction.

Note that just creating a holder variable isn't quite good enough -- I want different invocations of the MethodHandle to use different variables.


Solution

  • You can not create a local variable. If you want to use a value multiple times you could create a pass-through with identity and then copy the value using permuteArguments (or just use permuteArguments by itself if you can) e.g.:

    MethodHandle start = identity(String.class);
    MethodHandle sideEffect = lookup().findVirtual(PrintStream.class, "println", methodType(void.class, String.class)).bindTo(System.out);
    MethodHandle result = collectArguments(start, 0, sideEffect); // sideEffect needs to return nothing
    result = permuteArguments(result, methodType(String.class, String.class), 0, 0); // copy argument
    
    System.out.println((String) result.invokeExact("Hello")); // Hello\nHello
    

    Where the passed argument is used both as an argument to the side effect handle and as a return value. Essentially you can use the value multiple times.

    But there's really no easy one-fits-all answer when it comes to method handles. Perhaps the best advice I can give is to try and not use them as much as possible. i.e. write a static method with the code you need and then use a method handle to that in a longer method handle chain.