invoking a interface default method from within an InvocationHandler

Remi Forax forax at univ-mlv.fr
Wed Oct 22 11:18:48 UTC 2014


On 10/17/2014 11:58 AM, Paul Sandoz wrote:
> On Oct 16, 2014, at 12:43 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>
>> On 10/15/2014 06:54 PM, Paul Sandoz wrote:
>>> Hi Remi,
>>>
>>> I did some brief evaluation of this area.
>>>
>>> MethodHandleProxies.asInterfaceInstance currently does not support proxying to default methods. An InternalError will be thrown if a default method is invoked. It should be possible to fix using a trusted internal IMPL_LOOKUP to look up MHs that invokespecial. I believe this should be safe under the context of proxying.
>> Another solution is to do not rely on j.l.r.Proxy to implement asInterfaceInstance but to generate a proxy using ASM,
>> in that case, handling default methods is easy, just do nothing (i.e. do not override a default method).
>> It will also solve the fact that the proxies generated by asInterfaceInstance are currently super slow
>> because of the InvocationHandler API require boxing.
> That's a good point, it's more involved and it would be nice to reuse implementing classes keyed off the functional interface, since a field can be defined for the proxying MH. Hmm... i wonder if we can leverage InnerClassLambdaMetafactory.
>
>
>> The real solution in my opinion is to create yet another API,
> Yes, i am thinking just in the 9 time-frame, beyond that, as you indicate below, there is much more scope to improve this area (via invoke or a class dynamic).
>
> Paul.

I was stuck at Toronto airport Sunday,
so here is my gist on a possible Proxy 2.0 interface,
it cleanly manage the default method but do not manage the Object 
methods (equals, hashCode, toString)
which are like default method, java.lang.Object provide a kind of 
default implementation.

The API takes a MethodType and a ProxyHandler (which act as an 
InvocationHandler but at link time
and not at invocation time). It returns a method handle that acts as a 
factory method for the proxy.
The MethodType return type should be the interface to implement and is 
there is parameter types,
those are defined as fields of the proxy.

https://gist.github.com/forax/24620b80b9cd775e0bd1

The first example shows how to implement the same transformation as the 
lambda metafactory
without using a MethodHandleInfo. The second one shows how to delegate 
all calls to
a delegate object (a transparent proxy).

What the code does is to create a proxy genererated using ASM,
I've used the version of ASM which is bundled with the JDK to avoid a 
dependency.
Each method of the interface is implemented by an invokedynamic call, 
that calls a hidden BSM
that calls a special ProxyHandler with a j.l.r.Method as parameter.
In order to, at runtime, find the j.l.r.Method corresponding to a method 
of the interface,
I use the constant patching capability of Unsafe.defineAnonymousClass.

John, I've discovered a bug in the invokedynamic security checks,
if the invokedynamic call is in a class loaded by defineAnonymousClass, 
and the BSM is defined
in the host class of the anonymous klass with a package visibility, the 
BSM should be visible
but the current code throw a NoSuchMethodError.
Basically, the checks that check that the BSM is visible doesn't take 
into account the annonymous
klass visibility (see the gist).

cheers,
Rémi

>
>> lets call it proxy 2.0 that takes an interface and a bootstrap method
>> as parameter and generate a class that will call the BSM when calling a method of the proxy class the first time
>> (the BSM will be called with a 4th parameter which is a method handle corresponding to the called method
>> so one can use MHs.reflectAs to get the corresponding j.l.r.Method object if necessary).
>> For a default method, the 4th parameter will be a method handle created with findSuper, so a user can choose
>> to implement it or to delegate to this mh.
>> And asInterfaceInstance is just a foldArguments between the method handle taken as parameter and
>> an exactInvoker (or a genericInvoker if parameter types mismatch).
>>
>> Compared to a j.l.r.Proxy, the proxy 2.0 API also need a way to store fields (or at least values) inside the generated proxy class
>> and a way to query that fields inside the BSM. This can be done exactly like this is done by the lambda proxy,
>> instead of returning a proxy class, the proxy 2.0 API will return a method handle that acts as a factory for creating
>> proxy instances of the proxy class (if the factory takes no arguments, as for the lambda proxy, the same constant object can be returned).
>> To get a mh getter from inside the BSM, because the BSM already have the lookup object, all you need is a convention that says
>> that the field names are something like arg0, arg1, etc.
>>
>> The nice thing about this API is that it cleanly separate the information that can be process from proxied interface(s)
>> (by example, JavaEE annotations) and the ones, more dynamic, that are specific to a proxy instance.
>> It also removes one level of indirection compared to the InvocationHandler proxy.
>>
>>
>>
>> _______________________________________________
>> mlvm-dev mailing list
>> mlvm-dev at openjdk.java.net
>> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20141022/9f4af11c/attachment.html>


More information about the mlvm-dev mailing list