Invoking default methods from a Proxy's InvocationHandler in JDK9
John Rose
john.r.rose at oracle.com
Tue Jan 3 07:57:05 UTC 2017
On Jan 2, 2017, at 11:33 PM, Alan Bateman <Alan.Bateman at oracle.com> wrote:
>
> On 03/01/2017 07:17, Remi Forax wrote:
>
>> I do not think that the workaround to create a Lookup object by reflection works with 9 given that java.lang.invoke is not declared as an open package.
>>
>> John Rose has proposed to add a method to get a private Lookup object through sun.misc.Unsafe but as far as i know, this proposal goes nowhere.
>>
> I think we got a good place with MethodHandles.privateLookupIn. It's not going to allow you get a Lookup with private access to types in core modules such as java.base but it may be useful for some cases.
+1
As of JDK-8130227, it is possible to use Lookup.findSpecial to gain access to interface default methods.
See below for an example.
— John
/*
$ javac InvokeDefault.java && java -ea InvokeDefault
override foo on an OverridesDefault
default foo on an OverridesDefault
default foo on an OverridesDefault
$ java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+131)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+131, mixed mode)
*/
import java.lang.invoke.*;
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
interface HasDefault {
default String foo() { return "default foo on "+this; }
}
public class InvokeDefault {
private static class OverridesDefault implements HasDefault {
public String foo() { return "override foo on "+this; }
public String toString() { return "an OverridesDefault"; }
}
public static void main(String... av) throws Throwable {
HasDefault obj = new OverridesDefault();
System.out.println(obj.foo());
// ==> override foo on an OverridesDefault
System.out.println(HasDefaultShim.MH_foo().invoke(obj));
// ==> default foo on an OverridesDefault
System.out.println(InvokeDefault.MH_foo().invoke(obj));
// ==> default foo on an OverridesDefault
}
static MethodHandle MH_foo() {
try {
Class<?> it = HasDefault.class;
MethodHandle mh = MethodHandles.lookup().findSpecial(it, "foo", methodType(String.class), it);
return mh;
} catch (ReflectiveOperationException ex) {
throw new AssertionError(ex);
}
}
}
interface HasDefaultShim extends HasDefault {
static MethodHandle MH_foo() {
try {
Class<?> it = HasDefault.class;
Class<?> me = HasDefaultShim.class;
MethodHandle mh = MethodHandles.lookup().findSpecial(me, "foo", methodType(String.class), me);
assert(mh.type().parameterType(0) == me);
// force the MH to accept all implementations of the interface
mh = explicitCastArguments(mh, methodType(String.class, it));
assert(mh.type().parameterType(0) == it);
return mh;
} catch (ReflectiveOperationException ex) {
throw new AssertionError(ex);
}
}
}
More information about the jigsaw-dev
mailing list