代码模拟invokedynamic指令invokevirtual指令调用方法

来源:互联网 发布:手机时间提醒软件 编辑:程序博客网 时间:2024/06/03 19:37
public class TestC {    static interface Abc {        void a();    }    static class B implements Abc {        @Override        public void a() {            System.out.println("called");        }    }    public static void mainvirtual(String[] args) throws Throwable {        Object o = new B();        System.out.println(o.getClass());        MethodType type = MethodType.methodType(void.class);        MethodHandle mh = MethodHandles.lookup().findVirtual(o.getClass(), "a", type).bindTo(o);        mh.invokeExact();    }    public static void main(String[] args) throws Throwable {        Object o = new B();        System.out.println(o.getClass());        MethodType type = MethodType.methodType(void.class);        MethodHandle mh = MethodHandles.lookup().findVirtual(o.getClass(), "a", type).bindTo(o);        CallSite cs = new ConstantCallSite(mh);        cs.dynamicInvoker().invokeExact();    }    }

调用父类方法:

public class T1 {    public void a(){        System.out.println("t1");    }    public static void main(String[] args)            throws Throwable {        T2 t = new T2();        MethodType mt = MethodType.methodType(void.class);        MethodHandle amh = MethodHandles.lookup().findSpecial(T1.class, "a", mt, T1.class);        amh.invoke(t);    }}class T2 extends  T1{    public void a(){        System.out.println("t2");    }}class T3 extends  T2{    public void a(){        System.out.println("t3");    }}

https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/MethodHandles.Lookup.html#findSpecial-java.lang.Class-java.lang.String-java.lang.invoke.MethodType-java.lang.Class点击打开链接

MethodHandle有一些invokeDynamic的安全限制。
调用MethodHandles.lookup()的类要与findSpecial最后一个参数相同。

public class T1 {    public static void main(String[] args)            throws Throwable {        T3 t = new T3();        MethodType mt = MethodType.methodType(void.class);        MethodHandle amh = T2.lookup().findSpecial(T2.class, "a", mt, T2.class);        amh.invoke(t);    }}class T2{    public void a(){        System.out.println("t2");    }    public static MethodHandles.Lookup lookup(){        return MethodHandles.lookup();    }}class T3 extends  T2{    public void a(){        System.out.println("t3");    }}

当然这代码有点。。。你也可以倔强的这么做:

public class T1 {    public static void main(String[] args)            throws Throwable {        T3 t = new T3();        MethodType mt = MethodType.methodType(void.class);        MethodHandles.Lookup lookup = MethodHandles.lookup();        setField("lookupClass", lookup, T2.class, lookup.getClass());        MethodHandle amh = lookup.findSpecial(T2.class, "a", mt, T2.class);        amh.invoke(t);    }    public static void setField(String name, Object o, Object v, Class c)            throws NoSuchFieldException, IllegalAccessException {        Field f = c.getDeclaredField(name);        f.setAccessible(true);        f.set(o, v);    }}class T2{    public void a(){        System.out.println("t2");    }}class T3 extends  T2{    public void a(){        System.out.println("t3");    }}


暂时这么用着,有时间在研究。。。



原创粉丝点击