javassist 常用方法整理

javassist简介

一个比较好的例子:http://yucaifu1989.iteye.com/blog/1850500

比较好的文档:http://blog.csdn.net/u011425751/article/details/51917895

 

Javassist是一个开源的java字节码操作工具,主要是对已经编译好的class文件进行修改和处理,这里我写了一个简单的说明,复杂的请去看www.javassist.com的官方文档。

亲测实例

1、首先去官网下载jar http://jboss-javassist.github.io/javassist/ 里面有例子。

2、同样的使用使用jd-gui打开要修改的jar找到要修改的类名、方法名。

3、在2的基础上开始写修改代码

package start;

import javassist.ClassPool;

import javassist.CtClass;

import javassist.CtMethod;

public class Test1 {

public static void main(String[] args) throws Exception {

//创建类池(就是jar包),用来加载类

ClassPool cp=ClassPool.getDefault();

//jar包所在位置,如果这句代码不写,下面引用的类就是项目中引用的类

cp.insertClassPath("e:/checkLicense-3-3.1.jar");

//获取要修改的具体类,注意是完整路径包括类名

CtClass cc=cp.get("com.primeton.licensemanager.checklicense.LicenseCheckManager");

 

//获取要修改的具体方法

CtMethod cm=cc.getDeclaredMethod("checkHardware");

//开始对方法进行修改,这里是往方法的最前面插入了一条语句

cm.insertBefore("if(true)return;");

//保存,执行后会在工程下生成一个新的class文件,刷新一下项目即可看到

cc.writeFile();

}

 

}

 

 

 

 

4、查看新生成的文件,将生成的新class文件替换jar包以前的class即可使用了。

 

这块有意思,编译器将true生成了1!=0.....

 

在指定位置添加代码

// 在这个方法的182行添加关闭文件流的方法

method.insertAt(182, "fin.close();");

指定生成新class位置

ctClass.writeFile("path");


加入try cath

addCatch()

addCatch() 指的是在方法中加入try catch 块,需要注意的是,必须在插入的代码中,加入return $e代表 异常值。比如:  

CtMethod m = ...;  

CtClass etype = ClassPool.getDefault().get("java.io.IOException");  

m.addCatch("{ System.out.println($e); throw $e; }", etype);  

实际代码如下:  

try {  

    the original method body  

}  

catch (java.io.IOException e) {  

    System.out.println(e);  

    throw e;  

}  

重写方法体

//获取要修改的具体方法

CtMethod cm=cc.getDeclaredMethod("checkHardware");

cm.setBody("System.out.println(\"\");");

 

cm.setBody();方法可以重新设置方法体的内容。

cm.setName();重新设置方法名字。

使用方法中的参数

Javassist也提供了一些特殊的变量来代表方法参 数:$1,$2,$args...要注意的是,插入的source文本中不能引用方法本地变量的声明,但是可以允许声明一个新的方法本地变量,除非在程序 编译时加入-g选项。

 

$0代表的是this$1代表方法参数的第一个参数、$2代表方法参数的第二个参数,以此类推,$N代表是方法参数的第N个。例如:  

 

1.     //实际方法  

2.     void move(int dx, int dy)   

3.     //javassist  

4.     CtMethod m = cc.getDeclaredMethod("move");  

5.     //打印dx,和dy  

6.     m.insertBefore("{ System.out.println($1); System.out.println($2); }");  

7.     注意:如果javassist改变了$1的值,那实际参数值也会改变。  

 

 

1. $args 指的是方法所有参数的数组,类似Object[],如果参数中含有基本类型,则会转成其包装类型。需要注意的时候,$args[0]对应的是$1,而不是$0$0!=$args[0],$0=this  

 

 

使用类中定义的属性(字段)

$0 是代表this 也就是对象自己,所以直接使用 $0.字段 进行赋值或者使用即可。

例如字段名字叫 status 就可以写成 $0.status=1;

 

注意:目前可以确定用这种方式对字段进行赋值是没问题的,使用字段的方法还没有测试过。

使用类中定义的方法

与使用字段方法相似,$0.方法名

例如:方法名字叫 get() 就可以写成 $0.get();

修改构造方法

//获取构造方法集合,也可以指定获取指定参数的构造方法

CtClass cc=....;

CtConstructor[] ctc= cc.getConstructors();

 

//使用某个构造方法,与普通方法操作相同

ctc[0].insertAfter("{return ;}");

 

你可能感兴趣的:(Java反编译)