bytecode 生成器

发布时间 2023-05-15 09:13:00作者: Inshua

基础 objectweb asm 很难用,找了几个高级点的。

  • activej codegen 这个库很像 .net DLR 风格,采用 Expression 抽象,例如 Expressions.add(), Expressions.loop()。我发现它好几年了,这两天真正用的时候发现变量声明都搞不定。查看 nashorn 的源码,其风格也与此类似,现在 nashorn 都关闭了,如 nashorn 将此部分作为组件分享出来也是一大遗产了。
  • Apache Commons BCEL] 这个库基本在手写 bytecode,太吃力了。
  • javaassist,类似 codedom 的思路,生成 java 代码,借助 javac 编译为 bytecode,它把重点放到类的热插拔了
  • Byte Buddy 不好用,已经忘了怎么个不好用
  • cojen/Maker 最终使用的是这个,简单优雅:
        ClassMaker runnableClassMaker = ClassMaker.begin().public_().implement(Runnable.class);
        runnableClassMaker.addConstructor().public_();
        MethodMaker runMethod = runnableClassMaker.addMethod(void.class, "run").public_();
        org.cojen.maker.Variable i = runMethod.var(int.class).set(0);
        org.cojen.maker.Variable j = runMethod.var(int.class).set(0);
        org.cojen.maker.Variable sum = runMethod.var(int.class).set(0);
        org.cojen.maker.Variable op = runMethod.var(opClass).set(runMethod.new_(opClass));
        i.set(0);
        Label loop1 = runMethod.label().here();
            j.set(0);
            Label loop2 = runMethod.label().here();
                sum.inc(i.add(j));
            j.inc(1);
            j.ifLt(10000, loop2);
        i.inc(1);
        i.ifLt(10000, loop1);
        runMethod.var(System.class).field("out").invoke("println", runMethod.concat("sum: ", sum));

        Class<?> run = runnableClassMaker.finish();

这是一个个人作品,大量的参数类型是 object,这不是一种好的设计,但实际用的时候问题倒是不大,因为函数设计比较符合直觉。