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, 1 , 2,$args…要注意的是,插入的source文本中不能引用方法本地变量的声明,但是可以允许声明一个新的方法本地变量,除非在程序 编译时加入-g选项。

0this 0 代 表 的 是 t h i s , 1代表方法参数的第一个参数、 2, 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( 1 ) ; S y s t e m . o u t . p r i n t l n ( 2); }”);

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

  8. argsObject[] a r g s 指 的 是 方 法 所 有 参 数 的 数 组 , 类 似 O b j e c t [ ] , 如 果 参 数 中 含 有 基 本 类 型 , 则 会 转 成 其 包 装 类 型 。 需 要 注 意 的 时 候 , args[0]对应的是 1, 1 , 而 不 是 0, 0!= 0 ! = args[0],$0=this。

使用类中定义的属性(字段)
0this使 0 是 代 表 t h i s 也 就 是 对 象 自 己 , 所 以 直 接 使 用 0.字段 进行赋值或者使用即可。

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

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

使用类中定义的方法
与使用字段方法相似,$0.方法名

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

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

CtClass cc=….;

CtConstructor[] ctc= cc.getConstructors();

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

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

转载自http://blog.csdn.net/qq_24209665/article/details/75528386

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值