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