您的位置:首页 > 编程语言

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

2017-06-02 18:59 351 查看
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 href="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" target=_blank>点击打开链接

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");
}
}

暂时这么用着,有时间在研究。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐