@Override MethodHandle lookup(Method method) throws ReflectiveOperationException { MethodType methodType = MethodType.methodType(method.getReturnType(), method.getParameterTypes()); return getLookup(method.getDeclaringClass()).findSpecial(method.getDeclaringClass(), method.getName(), methodType, method.getDeclaringClass()); }
@Override public MethodHandle run() throws Exception { return MethodHandles.lookup().findSpecial( ReevaluatingReference.class, "replacePayLoad", MethodType.methodType(Object.class), ReevaluatingReference.class); } });
private static MethodHandle doLookup(Method method, Lookup lookup) throws NoSuchMethodException, IllegalAccessException { MethodType methodType = MethodType.methodType(method.getReturnType(), method.getParameterTypes()); if (Modifier.isStatic(method.getModifiers())) { return lookup.findStatic(method.getDeclaringClass(), method.getName(), methodType); } return lookup.findSpecial(method.getDeclaringClass(), method.getName(), methodType, method.getDeclaringClass()); }
@Override public Object invoke(ConfigHandler handler, Object[] args, Object proxy) { try { if (SystemUtils.IS_JAVA_1_8) { // hack to invoke default method of an interface reflectively Constructor<MethodHandles.Lookup> lookupConstructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, Integer.TYPE); if (!lookupConstructor.isAccessible()) { lookupConstructor.setAccessible(true); } return lookupConstructor.newInstance(configInterface, MethodHandles.Lookup.PRIVATE) .unreflectSpecial(configMethod, configInterface) .bindTo(proxy) .invokeWithArguments(args); } else { return MethodHandles.lookup() .findSpecial(configInterface, configMethod.getName(), MethodType.methodType(configMethod.getReturnType(), configMethod.getParameterTypes()), configInterface) .bindTo(proxy) .invokeWithArguments(args); } } catch (Throwable throwable) { throw new RuntimeException("Error invoking default method of config interface", throwable); } }
/** * Performs a findSpecial on the underlying lookup. Converts any encountered {@link IllegalAccessException} into an * {@link IllegalAccessError} and a {@link NoSuchMethodException} into a {@link NoSuchMethodError}. * * @param declaringClass class declaring the method * @param name the name of the method * @param type the type of the method * @return a method handle for the method * @throws IllegalAccessError if the method is inaccessible. * @throws NoSuchMethodError if the method does not exist. */ public MethodHandle findSpecial(Class<?> declaringClass, String name, MethodType type) { try { return lookup.findSpecial(declaringClass, name, type, declaringClass); } catch(IllegalAccessException e) { final IllegalAccessError ee = new IllegalAccessError("Failed to access special method " + methodDescription( declaringClass, name, type)); ee.initCause(e); throw ee; } catch(NoSuchMethodException e) { final NoSuchMethodError ee = new NoSuchMethodError("Failed to find special method " + methodDescription( declaringClass, name, type)); ee.initCause(e); throw ee; } }
/** * Performs a findSpecial on the underlying lookup. Converts any encountered {@link IllegalAccessException} into an * {@link IllegalAccessError} and a {@link NoSuchMethodException} into a {@link NoSuchMethodError}. * * @param declaringClass class declaring the method * @param name the name of the method * @param type the type of the method * @return a method handle for the method * @throws IllegalAccessError if the method is inaccessible. * @throws NoSuchMethodError if the method does not exist. */ public MethodHandle findSpecial(final Class<?> declaringClass, final String name, final MethodType type) { try { return lookup.findSpecial(declaringClass, name, type, declaringClass); } catch(final IllegalAccessException e) { final IllegalAccessError ee = new IllegalAccessError("Failed to access special method " + methodDescription( declaringClass, name, type)); ee.initCause(e); throw ee; } catch(final NoSuchMethodException e) { final NoSuchMethodError ee = new NoSuchMethodError("Failed to find special method " + methodDescription( declaringClass, name, type)); ee.initCause(e); throw ee; } }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { boolean hasAnnotation = method.getAnnotation(Query.class) != null; if(hasAnnotation) { QueryTypeAndQuery qs = extractQueryAnnotation(clazz, method); return qs.type.apply(qs.query, qs.rowMapperClass, jdbc, method, args, columnMapperFactories.set, parameterConverters.set); } else if(method.getReturnType().equals(NamedParameterJdbcTemplate.class) && args == null) { return jdbc; } else if(IS_DEFAULT_METHOD != null && (boolean) IS_DEFAULT_METHOD.invoke(method)) { final Class<?> declaringClass = method.getDeclaringClass(); final MethodHandle handle; if(PRIVATE_LOOKUP_IN != null) { MethodType methodType = MethodType.methodType(method.getReturnType(), method.getParameterTypes()); handle = MethodHandles.lookup().findSpecial(declaringClass, method.getName(), methodType, declaringClass); } else { handle = LOOKUP_CONSTRUCTOR.newInstance(declaringClass, MethodHandles.Lookup.PRIVATE).unreflectSpecial(method, declaringClass); } return handle.bindTo(proxy).invokeWithArguments(args); } else { throw new IllegalArgumentException(String.format("missing @Query annotation for method %s in interface %s", method.getName(), clazz.getSimpleName())); } } }
@Override @Ignore protected final Object $evaluate$(int $index$) { java.lang.String methodName = "$"+$index$; try { MethodHandle handle = lookup.findSpecial(subclass, methodName, methodType, subclass); // by delegating to the (anonymous) subclass `this` // will have the subclasses type and it can use // invokeExact(), where this class could not // (because we can't cast or even name the type // of this) return $invoke$(handle); } catch (Throwable e) { throw new RuntimeException(e); } } }
@Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { if (VersionFinder.JAVA_MAJOR_VERSION == 8) { final Constructor<Lookup> constructor = Lookup.class .getDeclaredConstructor(Class.class); constructor.setAccessible(true); constructor.newInstance(cls).in(cls).unreflectSpecial(method, cls).bindTo(proxy) .invokeWithArguments(); } else { // N.B. in testing, this didn't work... MethodHandles .lookup().findSpecial(cls, methodName, MethodType.methodType(returnType, new Class[0]), cls) .bindTo(proxy).invokeWithArguments(); } return null; } });
/** * Apply the chain of transforms and bind them to a special method specified * using the end signature plus the given class and name. The method will * be retrieved using the given Lookup and must match the end signature * exactly. * * If the final handle's type does not exactly match the initial type for * this Binder, an additional cast will be attempted. * * @param lookup the MethodHandles.Lookup to use to look up the method * @param name the name of the method to invoke * @param caller the calling class * @return the full handle chain, bound to the given method * @throws java.lang.NoSuchMethodException if the method does not exist * @throws java.lang.IllegalAccessException if the method is not accessible */ public MethodHandle invokeSpecial(MethodHandles.Lookup lookup, String name, Class<?> caller) throws NoSuchMethodException, IllegalAccessException { return invoke(lookup.findSpecial(type().parameterType(0), name, type().dropParameterTypes(0, 1), caller)); }
@Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { if (VersionFinder.JAVA_MAJOR_VERSION == 8) { final Constructor<Lookup> constructor = Lookup.class .getDeclaredConstructor(Class.class); constructor.setAccessible(true); constructor.newInstance(cls).in(cls).unreflectSpecial(method, cls).bindTo(proxy) .invokeWithArguments(); } else { // N.B. in testing, this didn't work... MethodHandles .lookup().findSpecial(cls, methodName, MethodType.methodType(returnType, new Class[0]), cls) .bindTo(proxy).invokeWithArguments(); } return null; } });
public static MethodHandle toMethodHandle(Handle handle, ClassLoader classLoader, MethodHandles.Lookup lookup) throws Exception { MethodType type = MethodType.fromMethodDescriptorString(handle.getDesc(), classLoader); Class<?> owner = classLoader.loadClass(handle.getOwner().replace('/', '.')); switch (handle.getTag()) { case H_INVOKESTATIC: return lookup.findStatic(owner, handle.getName(), type); case H_INVOKEVIRTUAL: case H_INVOKEINTERFACE: return lookup.findVirtual(owner, handle.getName(), type); case H_INVOKESPECIAL: return lookup.findSpecial(owner, handle.getName(), type, owner); case H_NEWINVOKESPECIAL: return lookup.findConstructor(owner, type); default: throw new AssertionError("Unexpected handle type: " + handle); } }
public static MethodHandle toMethodHandle(Handle handle, ClassLoader classLoader, MethodHandles.Lookup lookup) throws Exception { MethodType type = MethodType.fromMethodDescriptorString(handle.getDesc(), classLoader); Class<?> owner = classLoader.loadClass(handle.getOwner().replace('/', '.')); switch (handle.getTag()) { case H_INVOKESTATIC: return lookup.findStatic(owner, handle.getName(), type); case H_INVOKEVIRTUAL: case H_INVOKEINTERFACE: return lookup.findVirtual(owner, handle.getName(), type); case H_INVOKESPECIAL: return lookup.findSpecial(owner, handle.getName(), type, owner); case H_NEWINVOKESPECIAL: return lookup.findConstructor(owner, type); default: throw new AssertionError("Unexpected handle type: " + handle); } }
import java.lang.invoke.*; import java.util.function.Supplier; public class LambdaSuper { public static void main(String[] args) throws Throwable { MethodHandles.Lookup l=MethodHandles.lookup(); MethodType mt=MethodType.methodType(String.class); MethodHandle target=l.findSpecial(Object.class, "toString", mt, LambdaSuper.class); Supplier<String> s=(Supplier)LambdaMetafactory.metafactory(l, "get", MethodType.methodType(Supplier.class, LambdaSuper.class), mt.generic(), target, mt).getTarget().invokeExact(new LambdaSuper()); System.out.println(s.get()); } @Override public String toString() { return "overridden method"; } }
private NameEnvironmentAnswer superFindType(final char[][] compoundName, final char[] moduleName) { try { final MethodHandle superFindType = MethodHandles.lookup() .findSpecial(FileSystem.class, "findType", MethodType.methodType(NameEnvironmentAnswer.class, char[][].class, char[].class), FileSystemWithOverride.class); return (NameEnvironmentAnswer) superFindType.invoke(this, compoundName, moduleName); } catch (final Throwable e) { throw new SdkException(e); } }
private boolean superHasCompilationUnit(final char[][] qualifiedPackageName, final char[] moduleName, final boolean checkCUs) { try { final MethodHandle superHasCompilationUnit = MethodHandles.lookup() .findSpecial(FileSystem.class, "hasCompilationUnit", MethodType.methodType(boolean.class, char[][].class, char[].class, boolean.class), FileSystemWithOverride.class); return (Boolean) superHasCompilationUnit.invoke(this, qualifiedPackageName, moduleName, checkCUs); } catch (final Throwable e) { throw new SdkException(e); } }
private Object invokeDefaultMethodJava9(Object target, Method method, Object[] params) throws Throwable { return MethodHandles.lookup() .findSpecial( proxied, method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes()), proxied) .bindTo(target) .invokeWithArguments(params); }
private NameEnvironmentAnswer superFindType(final char[] typeName, final char[][] packageName, final char[] moduleName) { try { final MethodHandle superFindType = MethodHandles.lookup() .findSpecial(FileSystem.class, "findType", MethodType.methodType(NameEnvironmentAnswer.class, char[].class, char[][].class, char[].class), FileSystemWithOverride.class); return (NameEnvironmentAnswer) superFindType.invoke(this, typeName, packageName, moduleName); } catch (final Throwable e) { throw new SdkException(e); } }
@Override public CallSite invokeSpecial(Lookup caller, String methodName, MethodType signature, Class<?> owner) throws ReflectiveOperationException { try { return new ConstantCallSite(caller.findSpecial(owner, methodName, signature, caller.lookupClass())); } catch (ReflectiveOperationException e) { return null; } }
@Override MethodHandle lookup(Method method) throws ReflectiveOperationException { MethodType methodType = MethodType.methodType(method.getReturnType(), method.getParameterTypes()); return getLookup(method.getDeclaringClass()).findSpecial(method.getDeclaringClass(), method.getName(), methodType, method.getDeclaringClass()); }