Java 编程的动态性,第 7 部分: 用 BCEL 设计字节码
2010-03-18 00:00:00 来源:WEB开发网就 像 org.apache.bcel.classfile.JavaClass 是使用 BCEL 分析现有类的起点一样, org.apache.bcel.generic.ClassGen 是创建新类的起点。它还用于修改现有的类——为了处理这种情况,有一个以 JavaClass 实例为参数的构造函数,并用它初始化 ClassGen 类信息。修改了类以后,可以通过调用一个返回 JavaClass 的方法从 ClassGen 实例得到可使用的类表示,它又可以转换为一个二进制类表示。
听起来有些乱?我想是的。事实上,在两个包之间来回转是使用 BCEL 的一个最主要的缺点。重复的类结构总有些碍手碍脚,所以如果频繁使用 BCEL,那么可能需要编写一个包装器类,它可以隐藏其中一些不同之处。在本文中,我将主要使用 org.apache.bcel.generic 包类,并避免使用包装器。不过在您自己进行开发时要记住这一点。
除了 ClassGen , org.apache.bcel.generic 包还定义了管理不同类组件的结构的类。这些结构类包括用于处理常量池的 ConstantPoolGen 、用于字段和方法的 FieldGen 和 MethodGen 和处理一系列 JVM 指令的 InstructionList 。最后, org.apache.bcel.generic 包还定义了表示每一种类型的 JVM 指令的类。可以直接创建这些类的实例,或者在某些情况下使用 org.apache.bcel.generic.InstructionFactory helper 类。使用 InstructionFactory 的好处是它处理了许多指令构建的簿记细节(包括根据指令的需要在常量池中添加项)。在下面一节您将会看到如何使所有这些类协同工作。
用 BCEL 进行类操作
作为使用 BCEl 的一个例子,我将使用 第 4 部分中的一个 Javassist 例子——测量执行一个方法的时间。我甚至采用了与使用 Javassist 时的相同方式:用一个改过的名字创建要计时的原方法的一个副本,然后,通过调用改名后的方法,利用包装了时间计算的代码来替换原方法的主体。
更多精彩
赞助商链接