On 10/17/2014 11:58 AM, Paul Sandoz wrote:
On Oct 16, 2014, at 12:43 PM, Remi Forax <fo...@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@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to