Invoking default methods from a Proxy's InvocationHandler in JDK9

Peter Levart peter.levart at gmail.com
Tue Jan 3 07:20:12 UTC 2017


Hi Matthew,

On 01/03/2017 04:28 AM, Matthew Hall wrote:
> I'm a member of the JDBI [1] project, an open source SQL access library
> atop JDBC.
>
> A major part of our API provides implementations of declarative interfaces
> defined by users (similar to MyBatis). Interface methods may be default (in
> which case the default method implementation is used) or abstract (in which
> case JDBI provides the implementation).
>
> We're using JDK 8, and we use java.lang.reflect.Proxy and InvocationHandler
> to provide declarative interface implementations for our users.
>
> Prior to release of JDK 8, it appears that the subject of enhancing Proxies
> for default methods was discussed [2], but ultimately did not make it into
> the release.
>
> The root of the problem is that the generated Proxy class overrides all
> methods in the proxy interfaces. This means that the interface default
> methods are now superclass methods to the proxy class, which makes them
> un-invokable from outside code--including the InvocationHandler.
>
> As far as we can tell, the _only_ way to invoke a default method--on a
> proxy, from an InvocationHandler--is to resort to some horrible
> setAccessible shenanigans [3].
>
> Specifically, we have to:
> 1. Call Constructor.setAccessible(true) to make the private constructor
> MethodHandles.Lookup(Class<?> lookupClass, int allowedModes) accessible,
> 2. Invoke that private constructor to instantiate a MethodHandles.Lookup
> with private (!) access to all the things,
> 3. Call Lookup.unreflectSpecial to get the MethodHandle for the default
> method, and
> 4. Invoke the method through the MethodHandle.
>
> This is ugly, but it works--for now. If JDK 9 takes away access to
> setAccessible, it may cease to work.
>
> I found some discussion about this last summer [4], but it's hard to tell
> if anything came out of the discussion.
>
> Is there anything on the roadmap for JDK9 to allow a proxy's
> InvocationHandler to invoke default methods on proxies? Are there any
> existing proposals I should be aware of?

I have created a prototype last year:

http://mail.openjdk.java.net/pipermail/core-libs-dev/2016-June/041629.html

But I think the JDK 9 train has already left the station. So perhaps in 
JDK 10...

What you can do until then is to use other libraries (cglib, etc.). They 
can use sun.misc.Unsafe to "inject" proxy implementation classes into 
class loaders / modules / packages of interfaces they are implementing 
(similarly to what java.lang.reflect.Proxy is doing) and use 
MethodHandle(s) obtained from normal Lookup(s) in those classes to 
invoke the default implementations (similarly to what I have done in the 
prototype). I haven't checked, but maybe some other library already 
supports that?

Regards, Peter

>
> Regards,
>
> Matthew Hall
>
> [1] https://github.com/jdbi/jdbi/
> [2]
> http://mail.openjdk.java.net/pipermail/lambda-dev/2012-August/005675.html
> [3]
> https://github.com/jdbi/jdbi/blob/jdbi3/sqlobject/src/main/java/org/jdbi/v3/sqlobject/DefaultMethodHandler.java
> [4]
> http://jigsaw-dev.1059479.n5.nabble.com/creating-proxies-for-interfaces-with-default-methods-td5711955.html



More information about the jigsaw-dev mailing list