bcel_BCEL的字节码工程

本文介绍了如何使用Apache字节码工程库(BCEL)进行字节码操作,与Javassist框架对比,并展示了BCEL在类工作中的应用。BCEL提供低级JVM指令级别的控制,但使用起来比Javassist复杂。作者通过示例展示了如何使用BCEL创建和修改类,包括方法的计时功能。BCEL还包括验证程序、反汇编程序等工具,广泛应用于多个项目。
摘要由CSDN通过智能技术生成

在本系列的最后三篇文章中,我向您展示了如何使用Javassist框架进行类工作。 这次,我将使用Apache字节码工程库(BCEL)来介绍一种非常不同的字节码操作方法。 BCEL在实际的JVM指令级别上运行,这与Javassist支持的源代码接口不同。 当您确实想控制程序执行的每个步骤时,低级方法使BCEL非常有用,但是对于两种情况都可以使用的情况,使用BCEL的工作也比使用Javassist复杂得多。

我将首先介绍基本的BCEL体系结构,然后将本文的大部分时间用于用BCEL重建我的第一个Javassist类工作示例。 我将快速浏览BCEL软件包中包含的一些工具以及开发人员在BCEL之上构建的一些应用程序。

BCEL班级访问

BCEL为您提供与Javassist相同的基本功能,以检查,编辑和创建Java二进制类。 与BCEL的明显区别是,所有内容都旨在在JVM汇编程序语言级别上工作,而不是Javassist提供的源代码接口。 幕后有一些更深层次的差异,包括在BCEL中使用两个单独的组件层次结构-一个用于检查现有代码,另一个用于创建新代码。 我将假设您熟悉本系列以前的文章中的Javassist(请参阅侧栏不要错过本系列的其余部分 )。 因此,在您开始使用BCEL时,我将集中讨论可能会使您感到困惑的差异。

与Javassist一样,BCEL的类检查方面基本上可以复制通过Reflection API直接在Java平台中提供的功能。 在类工作工具包中,此重复是必要的,因为通常在修改完类之后 ,才希望加载正在使用的类。

BCEL在org.apache.bcel包中提供了一些基本的常量定义,但是除了这些定义之外,所有与检查相关的代码都在org.apache.bcel.classfile包中。 该包中的起点是JavaClass类。 在使用常规Java反射时,此类在使用BCEL访问类信息中的作用与java.lang.Class相同。 JavaClass定义了获取类的字段和方法信息的方法,以及有关超类和接口的结构信息。 与java.lang.Class不同, JavaClass还提供对类的内部信息的访问,包括常量池和属性,以及完整的二进制类表示形式(字节流)。

JavaClass实例通常是通过解析实际的二进制类来创建的。 BCEL提供了org.apache.bcel.Repository类来为您处理解析。 默认情况下,BCEL解析并缓存在JVM类路径中找到的类的表示,从org.apache.bcel.util.Repository实例获取实际的二进制类表示(请注意程序包名称中的差异)。 org.apache.bcel.util.Repository实际上是二进制类表示源的接口。 您可以替换其他路径来查找类文件,或使用其他访问类信息的方式来代替使用类路径的默认源。

换班

除了对类组件的反射式访问之外, org.apache.bcel.classfile.JavaClass还提供了用于更改类的方法。 您可以使用这些方法将任何类组件设置为新值。 但是,它们通常没有很多直接用途,因为包中的其他类不支持以任何合理的方式构造组件的新版本。 而是在org.apache.bcel.generic包中提供了一整套单独的类,它们提供了由org.apache.bcel.classfile类表示的相同组件的可编辑版本。

就像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处理常量池, FieldGenMethodGen的领域和方法, InstructionList用的JVM指令序列工作。 最后, org.apache.bcel.generic包还定义了表示每种JVM指令类型的类。 您可以直接创建这些类的实例,或者在某些情况下,使用org.apache.bcel.generic.InstructionFactory帮助器类。 使用InstructionFactory的优点是,它可以为您处理许多指令构建的簿记细节(包括

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值