论坛首页 综合技术论坛

反射工具包(字节码生成)

浏览 1520 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2015-10-11  

 

 

ReflectionUtil

反射工具包,利用反射的API直接生成Java字节码,提高执行效率。

普通方法调用

所有的命令最终生成到Invoker对象的invoke方法中

public Object invoke(Object[] args);

具体使用如下:

InvokerBuilder builder=InvokerBuilder.getInstance();
Method concat = String.class.getMethod("concat", new Class[]{String.class});
Method println = PrintStream.class.getMethod("println", new Class[]{String.class});
builder.constant("hello") //定义常量
        .store("end") //赋值给变量end 以上两句相当于String end = "hello"
        .methodInvoke(concat, Ops.$(0), Ops.v("end")) //调用invoke方法参数数组中的第0个值的concat方法,参数为变量end
    .store("tt")//将以上方法的返回值赋值给tt
    .staticField(System.class, "out") //获取System.out对象
    .constant("hello world!") //定义常量
    .methodInvoke(println)  //调用Sytem.out的println对象
    .ret("tt"); //返回tt

以上的所有操作,相当于直接编写以下代码

public class Generate$2055281021
  implements Invoker
{
  public Object invoke(Object[] paramArrayOfObject)
  {
    String str1 = "hello";
    String str2 = ((String)paramArrayOfObject[0]).concat(str1);
    System.out.println("hello world!");
    return str2;
  }
}

创建对象

直接调用new创建 具体代码如下:

InvokerBuilder builder=InvokerBuilder.getInstance();
Constructor<StringBuilder> init=StringBuilder.class.getConstructor(String.class);
Method append = StringBuilder.class.getMethod("append", String.class);
Method toString=Object.class.getMethod("toString", new Class[]{});
builder.constant("hello") //定义常量
    .store("a") //赋值给变量a
    .newInstance(StringBuilder.class, init,Ops.v("a")) //调用new指令,创建对象同时调用构造函数
    .store("sb")//赋值给sb变量
    .constant("world")//定义常量"world"
    .store("t") //赋值给变量t
    .methodInvoke(append, Ops.v("sb"), Ops.v("t")) //调用append方法
    .methodInvoke(toString) //调用toString
    .ret();  //返回以上调用的结果

以上所有操作相当于直接编写以下代码:

public class Generate$918221580
  implements Invoker
{
  public Object invoke(Object[] paramArrayOfObject)
  {
    String str1 = "hello";
    StringBuilder localStringBuilder = new StringBuilder(str1);
    String str2 = "world";
    return localStringBuilder.append(str2).toString();
  }
}

注意:在调用newInstance时,会同时调用构造方法和dup指令(将新对象的引用复制一份到栈顶),如果仅仅是调用构造方法而不使用新生成的对象(复制或作为方法的参数等),在调用完newInstance后要执行pop操作。

dump及写文件

编写完所有指令后,可以将字节码dump成jvm指令或写入文件中。使用如下:

InvokerBuilder builder=InvokerBuilder.getInstance();
Method concat = String.class.getMethod("concat", new Class[]{String.class});
builder.constant("hello").constant("world").methodInvoke(concat).ret();
ByteArrayOutputStream bos=new ByteArrayOutputStream();
builder.dump(bos);
System.out.println(new String(bos.toByteArray()));
builder.store2file("d:/tt/ttt1.class");

输出如下:

public class org.cc.Generate$918221580 extends java.lang.Object implements org.cc.common.reflection.core.Invoker{
public org.cc.Generate$918221580();
  Code:
   0:   aload_0
   1:   invokespecial   #10; //Method java/lang/Object."<init>":()V
   4:   return

public java.lang.Object invoke(java.lang.Object[]);
  Code:
   0:   ldc #14; //String hello
   2:   ldc #16; //String world
   4:   invokevirtual   #22; //Method java/lang/String.concat:(Ljava/lang/String;)Ljava/lang/String;
   7:   areturn
}

github地址:https://github.com/DreamLee471/ReflectionUtil

更多使用参见sample

有任何疑问可直接发邮件到dreamlee471@gmail.com

论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics