Search code examples
javaperformancetype-conversioninvokemethodhandle

Java 8 | Using MethodHandle#invokeExact on fields dynamically


My goal is to create a MethodHandle that, by passing a class and a field name, reads that field with a MethodHandle getter and returns the value.

With this method I wanted to return an arbitrary object:

return new ConstantCallSite(MethodHandles.lookup().unreflectGetter(f).asType(MethodType.methodType(Object.class))).dynamicInvoker();

I received the Field f via Reflections. The problem now is that when this method is executed, the typical error for invokeExact (WrongMethodTypeException) occurs:

WrongMethodTypeException: cannot convert MethodHandle(TestClass)String to ()Object

This also applies to ints, floats, etc. In another thread I also already read that you can use invokeExact dynamically if the return of MethodHandle is changed to Object. Here is a code snippet from the method, which makes use of passing a static final MethodHandle:

return (T) handle.invokeExact(testObject);

Using MethodHandle#invoke is rather out of the question for me, as I'm after performance. Without invokeExact I could possibly also fall back on using only reflections.

Does anyone know a way to do this or a workaround with similar performance? The latter plays a big role in the project. I thank those in advance who could possibly help with this problem.


Solution

  • A (non-static) getter needs an instance to retrieve the field's value from. You should be able to make this work by adding another Object parameter to the erased method type:

    return MethodHandles.lookup().unreflectGetter(f).asType(MethodType.methodType(Object.class, Object.class));
    

    (Also, there's no need to wrap the thing in a ConstantCallsite)