欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-07 10:30:17
...

 

 

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