Skip to content

Instantly share code, notes, and snippets.

@raphw
Last active May 9, 2018 19:07
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raphw/c1faf2f40e80afce6f13511098cfb90f to your computer and use it in GitHub Desktop.
Save raphw/c1faf2f40e80afce6f13511098cfb90f to your computer and use it in GitHub Desktop.
Method handle invoke special
package main;
import bar.Bar;
import qux.Qux;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Proxy;
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
test(Foo.class, Foo::foo); // interface in same module
test(Bar.class, Bar::foo); // interface in other module, exported
test(Qux.class, Qux::foo); // interface in other module, exported and opened
}
private static <T> void test(Class<? extends T> iface, Consumer<T> consumer) {
Object instance = Proxy.newProxyInstance(
Bar.class.getClassLoader(),
new Class<?>[]{iface},
(proxy, method, args) -> {
MethodHandles.Lookup lookup;
if (proxy.getClass().getModule().isNamed()) {
lookup = MethodHandles.privateLookupIn(iface, MethodHandles.lookup());
} else {
Main.class.getModule().addReads(proxy.getClass().getModule());
lookup = MethodHandles.privateLookupIn(proxy.getClass(), MethodHandles.lookup());
}
return lookup.findSpecial(
iface,
"foo",
MethodType.methodType(String.class, new Class<?>[0]),
iface
).bindTo(proxy).invokeWithArguments();
}
);
test(iface, iface.cast(instance), consumer);
}
private static <T> void test(Class<? extends T> iface, T instance, Consumer<T> consumer) {
try {
consumer.accept(instance);
System.out.println("Could invoke special method for " + iface);
} catch (Throwable throwable) {
System.out.println("Could NOT invoke special method for " + iface);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment