将代码添加到带有Instrumentation的Java类:ASM还是BCEL?

时间:2012-04-18 07:53:18

标签: java bytecode instrumentation java-bytecode-asm bcel

我正在编写一个游戏引擎/库,其中我有一个事件调度程序类,它通过调用“已注册”事件处理程序类的侦听器方法来调度事件。可以通过调用适当的调度程序方法向事件调度程序注册事件处理程序/侦听器。

这显然会导致一些样板代码用于注册每个事件处理程序(以及我的引擎的其他方面都有类似的bolierplate代码),所以我想知道 - 如何在加载期间使用Instrumentation添加所有必需的代码事件处理程序类,因此在编码时不需要使用事件调度程序进行显式注册 - 在程序运行时会自动添加对调度程序寄存器方法的调用。

我的理解是,为了使用Instrumentation,应该使用一些字节码修饰符API。我知道两个 - ASM和BCEL。我应该使用哪一个?显然,这是我想要做的一个简单的任务,所以我想要一个更容易学习和更好记录的那个。

编辑:这是一个具体的例子。

原始事件处理程序类:

@Handler //indicates this this class should be transformed
public class MouseEventHandler implements EventHandler<MouseEvent>
{
    //hidden default constructor
    public void handleEvent(MouseEvent event)
    { ... }
}

转型后:

@Handler
public class MouseEventHandler implements EventHandler<MouseEvent>
{
    public MouseEventHandler()
    {
        //add this line of code to default constructor
        Game.getEventDispatcher().addEventHandler(this);
    }
    public void handleEvent(MouseEvent event)
    { ... }
}

2 个答案:

答案 0 :(得分:22)

Java字节码库:

  • ASM快速且积极发展。
  • BCEL相对较慢。
  • 如果您不熟悉Java字节码,
  • Javassist可能最容易上手。
  • cglib建立在ASM之上,提供更高级别的抽象。
  • Byte Buddy通过DSL生成课程。积极维护并看到越来越多的使用。

然而,在进入字节码操作之前,我会考虑其他选项。

答案 1 :(得分:6)

将逻辑添加到几个类可能会很无聊,但除非你有很多处理程序,否则这就是我要去的方式。 保持简单

那就是说,

Game.registerHandler( this );

会更加面向对象。

在每个类中添加逻辑的替代方法是引入负责实例化处理程序的工厂

HandlerFactory.createMouseHandler();

方法createMouseHandler包含类似

的内容
Handler mh = new MousheHandler();
registerHandler(mh);
return mh;

如果你不想要这些选项,我会考虑方面框架(可能是AspectJ)或容器用于控制反转(可能是Spring IoC )。方面允许您注释您的源,并在选定的位置“编织”代码。 IoC容器允许您控制对象的生命周期(例如实例化)。两者都在场景后面使用字节码检测。

但是如果你想自己做仪器,我只能比较我个人使用的Javassist和ASM。

ASM 是低级别的,并且真正在java字节码的级别上运行。你必须熟悉它。该框架设计精良,手册非常好,而且它是一个很棒的库。一方面,它可以复杂化以替换字节码的模式,因为它需要所谓的“有状态”转换。另一方面,您可以完全控制字节码。

Javassist 更高级别。您不是在字节码的原始级别操作,稍高级别,例如字段读/写,消息发送,构造函数。此外,它允许您使用常规Java语法指定更改,然后由框架编译。 API有点混乱,因为该项目多年来不断发展。有关于框架的文档,但没有像ASM那样集中管理。