package org.jadira.reflection.access.invokedynamic; import java.lang.invoke.CallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.lang.reflect.Method; import org.dynalang.dynalink.DefaultBootstrapper; import org.jadira.reflection.access.api.MethodAccess; public class InvokeDynamicMethodAccess<C> implements MethodAccess<C> { private String methodName; private Method method; private Class<C> declaringClass; private Class<?> returnType; CallSite methodCallSite; MethodHandle mh; @SuppressWarnings("unchecked") private InvokeDynamicMethodAccess(Method m) { this.methodName = m.getName(); this.declaringClass = (Class<C>) m.getDeclaringClass(); this.method = m; this.returnType = (Class<?>) m.getReturnType(); methodCallSite = DefaultBootstrapper.publicBootstrap(null, "dyn:getMethod:" + methodName, MethodType.methodType(returnType, declaringClass, method.getParameterTypes())); mh = methodCallSite.dynamicInvoker(); } public static <C> InvokeDynamicMethodAccess<C> get(Method m) { return new InvokeDynamicMethodAccess<C>(m); } @Override public Class<C> declaringClass() { return declaringClass; } @Override public Class<?> returnClass() { return returnType; } @Override public Method method() { return method; } @Override public Object invoke(Object target, Object... args) throws IllegalArgumentException { try { return mh.invokeExact(target, args); } catch (Throwable e) { throw new IllegalArgumentException("Problem invoking {" + method.getName() + "} of object {" + System.identityHashCode(target) + "}: " + e.getMessage(), e); } } }