001package org.jadira.reflection.access.invokedynamic; 002 003import java.lang.invoke.CallSite; 004import java.lang.invoke.MethodHandle; 005import java.lang.invoke.MethodType; 006import java.lang.reflect.Method; 007 008import org.dynalang.dynalink.DefaultBootstrapper; 009import org.jadira.reflection.access.api.MethodAccess; 010 011public class InvokeDynamicMethodAccess<C> implements MethodAccess<C> { 012 013 private String methodName; 014 015 private Method method; 016 private Class<C> declaringClass; 017 private Class<?> returnType; 018 019 CallSite methodCallSite; 020 021 MethodHandle mh; 022 023 @SuppressWarnings("unchecked") 024 private InvokeDynamicMethodAccess(Method m) { 025 026 this.methodName = m.getName(); 027 028 this.declaringClass = (Class<C>) m.getDeclaringClass(); 029 this.method = m; 030 031 this.returnType = (Class<?>) m.getReturnType(); 032 033 methodCallSite = DefaultBootstrapper.publicBootstrap(null, "dyn:getMethod:" + methodName, MethodType.methodType(returnType, declaringClass, method.getParameterTypes())); 034 mh = methodCallSite.dynamicInvoker(); 035 } 036 037 public static <C> InvokeDynamicMethodAccess<C> get(Method m) { 038 039 return new InvokeDynamicMethodAccess<C>(m); 040 } 041 042 @Override 043 public Class<C> declaringClass() { 044 return declaringClass; 045 } 046 047 @Override 048 public Class<?> returnClass() { 049 return returnType; 050 } 051 052 @Override 053 public Method method() { 054 return method; 055 } 056 057 @Override 058 public Object invoke(Object target, Object... args) throws IllegalArgumentException { 059 060 try { 061 return mh.invokeExact(target, args); 062 } catch (Throwable e) { 063 throw new IllegalArgumentException("Problem invoking {" + method.getName() + "} of object {" 064 + System.identityHashCode(target) + "}: " + e.getMessage(), e); 065 } 066 } 067}