java.lang.reflect.Proxy and default methods - via MethodHandles
Remi Forax
forax at univ-mlv.fr
Mon Sep 10 10:29:37 PDT 2012
On 09/10/2012 07:20 PM, Peter Levart wrote:
> A nice way for InvocationHandler to access super default methods on interfaces implemented by dynamic proxy class could be to add new (default) method to InvocationHandler:
>
>
> public interface InvocationHandler
> {
> void init(MethodHandles.Lookup proxyLookup) default {}
>
> Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
> }
>
>
> ...this default method is a no-op, but can be overriden by new implementations.
>
> Now imagine we have the following interface:
>
> public interface A
> {
> void m() default
> {
> ...
> }
> }
>
>
> For this interface we would like to create a dynamic proxy that would be equivalent to the following class:
>
> class Aimpl implements A
> {
> public void m()
> {
> System.out.println("before");
> A.super.m();
> System.out.println("after");
> }
> }
>
>
> The InvocationHandler implementation for such dynamic proxy could look like this:
>
> class Ahandler implements InvocationHandler
> {
> private MethodHandle superA_m;
>
> @Override
> public void init(MethodHandles.Lookup proxyLookup)
> {
> try
> {
> superA_m = proxyLookup.findSpecial(A.class, "m", MethodType.methodType(void.class, new Class[0]), proxyLookup.lookupClass());
> }
> catch (NoSuchMethodException | IllegalAccessException e)
> {
> throw new AssertionError(e.getMessage(), e);
> }
> }
>
> @Override
> public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
> {
> System.out.println("before");
> superA_m.invoke((A)proxy);
> System.out.println("after");
> return null;
> }
> }
>
>
> I was about to implement such experimental proxy factory, but unfortunately the MethodHandles.Lookup.findSpecial() is not taking into account yet the fact that interfaces can have non-abstract methods, as it throws:
>
> Caused by: java.lang.IllegalAccessException: caller class must be a subclass below the method: defaultmeth.Test$A.m()void, from class defaultmeth.Test$Aproxy
> at java.lang.invoke.MemberName.makeAccessException(MemberName.java:507)
> at java.lang.invoke.MethodHandles$Lookup.restrictReceiver(MethodHandles.java:1228)
> at java.lang.invoke.MethodHandles$Lookup.accessSpecial(MethodHandles.java:758)
> at java.lang.invoke.MethodHandles$Lookup.findSpecial(MethodHandles.java:752)
>
> ...although Aproxy is a class implementing interface A...
>
> Maybe also a kind of "resolveSpecial" method is needed on Lookup to simplify the search for super method on an interface...
yes, it's an issue that will be soon resolved. It's on the jsr 292 agenda :)
Also if you use method handles, you can use them to specify a method
handle that will be used as handler
instead of using an InvocationHandler which unlike method handle
requires to box the parameter in an array.
>
>
> Regards, Peter
>
>
>
cheers,
Rémi
More information about the lambda-dev
mailing list