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