Hei Alan, maybe I am doing it wrong but this is my example. I created a module with two interfaces bar.Bar and qux.Qux that both define a default method String foo() { return "foo"; }. The module exports bar and exports and opens qux. >From another module that reads that first module I run the following code:
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); // works: interface in same module test(Bar.class, Bar::foo); // works not: interface in other module, exported test(Qux.class, Qux::foo); // works: interface in other module, exported and opened test(Bar.class, new Bar() { // works: explicit proxy @Override public String foo() { return Bar.super.foo(); } }, Bar::foo); test(Bar.class, new Bar() { // works not: explicit proxy with method handle @Override public String foo() { try { return (String) MethodHandles.lookup().findSpecial( Bar.class, "foo", MethodType.methodType(String.class, new Class<?>[0]), Bar.class ).bindTo(this).invokeWithArguments(); } catch (Throwable throwable) { throw new RuntimeException(throwable); } } }, Bar::foo); } private static <T> void test(Class<? extends T> iface, Consumer<T> consumer) { Object instance = Proxy.newProxyInstance( Bar.class.getClassLoader(), new Class<?>[]{iface}, (proxy, method, arguments) -> MethodHandles.privateLookupIn(iface, MethodHandles.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); } } } >From the code comments, some approaches work and some do not. What would I need to do differently? Thank you and best regards, Rafael 2018-04-09 9:33 GMT+02:00 Alan Bateman <alan.bate...@oracle.com>: > On 01/04/2018 22:02, Rafael Winterhalter wrote: > >> : >> >> 1. Java agents cannot define auxiliary classes. >> >> : >> The reason for >> using Unsafe is that many instrumentations need to define auxiliary >> classes >> to aid an instrumentation similar to javac which sometimes needs to define >> anonymous classes or even synthetic classes. For example, if a Java agent >> wants to register an event listener to some framework, such listeners >> often >> declare multiple methods what makes it impossible to fullfil the listener >> contract using a lambda expression. Instead, one typically injects an >> additional class into the same package as the instrumented class. >> > This seems a reasonable requirement. As you know, JSR-163 created this API > (and JVM TI) for tools to instrument code in mostly benign ways where any > additional agent provided helper classes are made visibility via the > appendToXXXClassLoaderSearch methods. I don't think the use-case of > dynamically generated helper classes came up, I don't recall it coming up > on serviceability-dev in the intervening years either. In any case, I think > there should be a way to support this scenario, it amounts to a > ClassFileTransformer providing the class bytes of additional classes to be > defined in the same runtime package as the class being loaded or > transformed. There are a number of API choices and it's probably best if we > bring proposals to serviceability-dev as that is where this API is > maintained. > > > : >> >> 2. Java proxies cannot invoke default methods of proxied interfaces >> >> The Java proxy API does not currently allow the invocation of an >> overridden >> default method since >> the InvocationHandler API only supplies an instance of >> java.lang.reflection.Method. >> > The issue of Proxies and default methods has come up on core-libs-dev a > few times. In the mean-time, JEP 274 added support for MethodHandles that > bind to non-abstract methods in interfaces. I just double checked and I can > create a proxy where the invocation handler creates a method handle to the > default method, binds it to proxy, and invokes it. I also checked the case > where the interface is public in an exported package of a named module. Can > you say a bit more, or provide an example, where you run into issues? I'm > wondering if you are running into an accessibility issue or something else. > > -Alan > >