使用DummyModifiedClass修改class
1. DummyModifiedClass dummy = new DummyModifiedClass(A.class);
传入的A.class为希望修改的类
dummy.modify("test", new Class[]{int.class, String}, new ModifiedMethodBody(){ @Override public void body(LocalVariable... args) { //TODO } });
上面的代码是修改方法test(int a, String b). 目前修改方法我们只允许修改方法内容,理论上讲也是可以修改方法的修饰符参数列表的,但是这的意义并不大,因为我们修改方法的主要目的是想增加一些业务逻辑,而不是将方法签名都改了,如果真是这样还不如新建一个方法。
上面的第三个参数就是我们修改的方法方法体。我们希望修改的业务逻辑在标记“//TODO”的位置上。我们能够在这里写入自己的逻辑。比如下面:
@Override public void body(LocalVariable... args) { GlobalVariable out = defType(System.class).field("out"); call(out, "println", val("Hello ASMSupport")) return_(); }
我们将方法修改成了只打印一句“Hello ASMSupport”,如果希望添加一个逻辑,就是计算方法执行时间,那么就需要调用方法被修改前的内容了,代码如下:
@Override public void body(LocalVariable... args) { LocalVariable time = var("time", long.class, call(System.class, "currentTimeMillis")); callOrig(); GlobalVariable out = defType(System.class).field("out"); call(out, "println", sub(call(System.class, "currentTimeMillis"), time)); return_(); }
上面的代码中callOrig()方法就是调用原方法的内容。如果原方法是有返回值的,就可以使用下面代码:
@Override public void body(LocalVariable... args) { LocalVariable time = var("time", long.class, call(System.class, "currentTimeMillis")); LocalVariable result = var("result", getOrigReturnType(), callOrig()); GlobalVariable out = defType(System.class).field("out"); call(out, "println", sub(call(System.class, "currentTimeMillis"), time)); return_(result); }
其中getOrigReturnType()就是获取被修改方法返回类型。
dummy.modifyConstructor(new Class[]{int.class, String.class}, new ModifiedMethodBody(){ @Override public void body(LocalVariable... args) { //TODO } });
和修改方法类似,但是没有传入方法名,因为是构造方法。但是在使用的时候注意,在修改构造方法的时候调用callOrig()是没有返回结果的。
dummy.modifyConstructor(new ModifiedMethodBody(){ @Override public void body(LocalVariable... args) { //TODO } });
和修改构造方法类似,但是没有传参数类型列表,同样调用callOrig()是没有返回结果的。
我们内置ClassLoader来完成我们生成的class的字节数组到class对象,当然也允许自定义classloader通过下面的方法
dummy.setClassLoader(classloader);