Hi Jake,
On 06/05/2016 08:28 AM, Jake Wharton wrote:
On Fri, Jun 3, 2016 at 10:58 AM Peter Levart <peter.lev...@gmail.com
<mailto:peter.lev...@gmail.com>> wrote:
InvocationHandler gets invoked for default methods, but it
has not provision to forward such calls to the default implementations
in the interfaces.
This isn't quite true. You can use MethodHandles to invoke the default
method if the interface is public:
Object returnValue = MethodHandles.lookup()
.in(declaringClass)
.unreflectSpecial(method, declaringClass)
.bindTo(proxy)
.invokeWithArguments(args);
You are right. It appears that such Lookup has more powers than bytecode.
If the interface is not public, things get a bit more tricky since you
need an instance which ignores the visibility. The only way to get at
this is through creating your own trusted instance for the interface type:
Constructor<Lookup> constructor =
Lookup.class.getDeclaredConstructor(Class.class, int.class);
constructor.setAccessible(true);
Object returnValue = constructor.newInstance(declaringClass, -1 /*
trusted */)
.unreflectSpecial(method, declaringClass)
.bindTo(proxy)
.invokeWithArguments(args);
That said, I'm all for an API that makes this easier! Please make sure
it handles non-public interface types as well.
Right, the changes I made to Proxy class generation, construct the
Lookup object in the proxy class' <clinit>. Such Lookup has access to
any superinterface method by virtue of the proxy class being able to
implement such interface (if it is a package-private interface, the
proxy class is generated in the same package; if it is an interface in a
non-exported package, the proxy class is generated in a dynamic module
and qualified export is added to the module holding the interface; etc...).
Regards, Peter