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