【问题标题】:Adding code to a Java class w/ Instrumentation: ASM or BCEL?使用 Instrumentation 向 Java 类添加代码:ASM 还是 BCEL?
【发布时间】:2012-04-18 07:53:18
【问题描述】:

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

这显然会导致一些用于注册每个事件处理程序的样板代码(并且我的引擎的其他方面也有类似的样板代码),所以我想知道 - 在加载过程中使用 Instrumentation 添加所有必要的代码怎么样事件处理程序类,因此在编码时不需要向事件调度程序显式注册 - 对调度程序的 register 方法的调用会在程序运行时自动添加。

据我了解,为了使用 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)
    { ... }
}

【问题讨论】:

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


    【解决方案1】:

    Java 字节码库:

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

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

    【讨论】:

    • bcel 已包含在 JDK 中
    • @alexander.box:是的,作为对 XSLTC 转换器 Xalan 的依赖,但它是非标准 API,并且还隐藏在 com.sun.org.apache.bcel.internal 包中!最好提供你自己的罐子。
    • 哦,虽然我正在这样做:当必须对类进行检测时,ASM 是一个非常好的选择。易于理解和使用。它还有一个非常好的文档。
    【解决方案2】:

    将逻辑添加到几个类可能很无聊,但除非你有成千上万的处理程序,否则我会这样做。 保持简单

    也就是说,

    Game.registerHandler( this );
    

    会更加面向对象。

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

    HandlerFactory.createMouseHandler();
    

    并且方法createMouseHandler 包含类似

    Handler mh = new MousheHandler();
    registerHandler(mh);
    return mh;
    

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2012-01-15
      • 2016-06-06
      • 2011-10-12
      • 2013-01-03
      • 2021-09-10
      • 1970-01-01
      • 1970-01-01
      • 2021-03-21
      • 1970-01-01
      相关资源
      最近更新 更多