Javassist学习笔记(一)

一,概述

Javassist是一个动态字节码生成框架,包括支持两种API,Java语言级别和字节码级别。其中有些特性是受限的或者不支持的,尤其是JDK1.5里的部分新特性。

最经常使用的是来提升POJO的能力。

具体技术内容请参考官方文档

http://www.csg.is.titech.ac.jp/~chiba/javassist/

二,ClassPool
ClassPool 缓存CtClass的池。体系有些类似java中的ClassLoader,有自己的命名空间。
JVM不允许动态加载类,因此Javassist也提供frozen能力;当然javassist还提供解冻能力。
Javassist还提供修剪pruning的能力,以节省内存。如果被修剪,那么一个类的方法元信息将不能再被访问,除了方法名,方法签名和annotations。一个被prune的类,经过writeFile()或者toBytecode()是不能再被解冻的。因为其元信息丢失。

在有些情景下,开发者需要组织自己的ClassPool体系结构。如果在Tomcat等存在多重ClassLoader的环境中。

ClassPool支持多种添加类路径的方式,如URL,Inputtream,byte[]等。

其最经典的使用方式

ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("test.Rectangle");
cc.setSuperclass(pool.get("test.Point"));
cc.writeFile();

CtClass可以从ClasPool中脱离,以节省内存,通过

cc.detach();

创建ClassPool的方式
ClassPool pool = ClassPool.getDefault(); //便捷方式,维护一个单例
等同于
ClassPool cp = new ClassPool(true);
等同于
ClassPool cp = new ClassPool();
cp.appendSystemPath();


在ClassPool加载类的体系中可以指定Child优先,通过如下代码:
child.childFirstLookup = true;


Javassist可以更改类名(未冻结)
CtClass.setName("newName");

或者更改已被冻结的类以创建新类

ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("Point");
cc.writeFile();
CtClass cc2 = pool.getAndRename("Point", "Pair");

三,使用ClassLoader

在要修改的类不能事先确定的情况下,不能使用上面的方式更改类,必须配合ClassLoader。当然Javassist也提供了ClassLoader的扩展。
CtClass.toClass();
需要提及的是要选对ClassLoader。例如使用bean对象的加载器

Class c = cc.toClass(bean.getClass().getClassLoader());


加载类时修改
使用javassist.Loader和其事件监听器机制

修改系统类
运行时动态重加载类(reload)

4. 内醒和定制Introspection and customization

Javassist 不能删除方法或者域成员;不能给方法添加参数,必须通过创建新的方法满足。
Javassist通过内联的方式给方法添加代码块。方法的局部变量名是无法得到的,除非用-g参数编译类。通过$做前缀来访问。
insertBefore(), insertAfter(), andaddCatch()

Javassist提供了各种类来帮助修改不同类型的数据,其中$在不同的类型中意义有所差别或者Not available.

javassist.expr.MethodCall
javassist.expr.ConstructorCall
javassist.expr.FieldAccess
javassist.expr.NewExpr
javassist.expr.NewArray
javassist.expr.Instanceof
javassist.expr.Cast
javassist.expr.Handler//处理异常

4.3 Adding a new method or field
添加方法时,如果方法之间有依赖调用,如果找不到定义则会失败。因此需要通过添加抽象方法的方式实现
CtClass cc = ... ;
CtMethod m = CtNewMethod.make("public abstract int m(int i);", cc);
CtMethod n = CtNewMethod.make("public abstract int n(int i);", cc);
cc.addMethod(m);
cc.addMethod(n);
m.setBody("{ return ($1 <= 0) ? 1 : (n($1 - 1) * $1); }");
n.setBody("{ return m($1); }");
cc.setModifiers(cc.getModifiers() & ~Modifier.ABSTRACT);
添加域,应该赋初始值。

注意:Javassist生成的类一般不需要特殊辅助即可运行,但有些特殊情况需要用到一下包
javassist.runtime

4.7限制
enums and generics have not been supported.使用范型时,以普通类型对待。

5. Bytecode level API
字节码级别的API提供了更强的能力,包括添加和删除成员(包括方法)。
6.范型
7. Varargs可变参数
Javassist不支持可变参数,将转成数组来访问。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值