代码模拟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");
}
}
暂时这么用着,有时间在研究。。。
相关文章推荐
- 代码清单17:调用截拦器,DefaultActionInvocation.invoke()方法的部分代码
- 《对“XXX::Invoke”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们》的问题的解决方法
- Android中performClick方法---代码调用点击事件(模拟去触摸控件)
- 在别人的程序的任意位置加上调用自己函数的代码,且不影响原程序执行的方法
- “由于代码已经过优化或者本机框架位于调用堆栈之上,无法计算表达式的值”的解决方法
- 【原创】ASP.NET后台代码调用前台javascript脚本的方法
- ASP.NET中,客户端利用 ASP.NET AJAX(Atlas)调用服务端方法的代码
- 用Delphi7编写代码时出现"dcc70.dll"调用失败的处理方法
- php调用C代码的方法详解和zend_parse_parameters函数详解
- 使用IDispatch::Invoke函数在C++中调用C#实现的托管类库方法
- 转:使用IDispatch::Invoke函数在C++中调用C#实现的托管类库方法
- ASP.NET后台代码调用前台javascript脚本的方法
- 在WinFrom应用中,如果使用后台线程来操作界面应调用Control.Invoke()方法
- C# 代码示例详尽剖析异步调用的两种方法
- ASP.NET AJAX框架调用后台代码的基本方法
- php调用C代码的方法详解
- 我转载的文章《.NET中统一的存储过程调用方法 》具体实现代码
- asp.net下利用JS实现对后台CS代码的调用方法
- [第一篇]先发布一个高亮代码在线html编辑器(.NET控件),附源码,调用方法说明
- ASP.NET中常用的26个优化性能方法---将调用密集型的 COM 组件迁移到托管代码