java.lang.reflect.Proxy and default methods - via MethodHandles
Peter Levart
peter.levart at marand.si
Mon Sep 10 10:20:39 PDT 2012
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...
Regards, Peter
More information about the lambda-dev
mailing list