14

我已经开始为我正在处理的编译器项目使用 ASM API。但是,我发现文档对于很多地方的新手来说都不是很清楚,我认为有一个很好的可靠示例来生成一个简单地打印“Hello, World!”的类。将是一个很好的例子。

目前,我可以生成一个带有 main() 的类(使用 ClassWriter、ClassVisitor 和 MethodVisitor 类),但我似乎无法弄清楚如何生成 main 的主体。谁能给我一个在 ASM 中生成类文件的示例:

  • 包含一个 main()
  • 在 main() 中创建一个本地字符串变量,其值为“Hello, World!”
  • 打印变量
4

2 回答 2

16

您可以使用 java 编译一个类,然后让 asm 打印出生成等效类所需的调用,

常问问题

ASMifierClassVisitor

ASMifierClassVisitor javadocs 实际上有 hello world 代码,

import org.objectweb.asm.*;

public class HelloDump implements Opcodes {

  public static byte[] dump() throws Exception {

     ClassWriter cw = new ClassWriter(0);
     FieldVisitor fv;
     MethodVisitor mv;
     AnnotationVisitor av0;

     cw.visit(49,
             ACC_PUBLIC + ACC_SUPER,
             "Hello",
             null,
             "java/lang/Object",
             null);

     cw.visitSource("Hello.java", null);

     {
         mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
         mv.visitVarInsn(ALOAD, 0);
         mv.visitMethodInsn(INVOKESPECIAL,
                 "java/lang/Object",
                 "<init>",
                 "()V");
         mv.visitInsn(RETURN);
         mv.visitMaxs(1, 1);
         mv.visitEnd();
     }
     {
         mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC,
                 "main",
                 "([Ljava/lang/String;)V",
                 null,
                 null);
         mv.visitFieldInsn(GETSTATIC,
                 "java/lang/System",
                 "out",
                 "Ljava/io/PrintStream;");
         mv.visitLdcInsn("hello");
         mv.visitMethodInsn(INVOKEVIRTUAL,
                 "java/io/PrintStream",
                 "println",
                 "(Ljava/lang/String;)V");
         mv.visitInsn(RETURN);
         mv.visitMaxs(2, 1);
         mv.visitEnd();
     }
     cw.visitEnd();

     return cw.toByteArray();
  }
}
于 2011-03-18T01:39:30.160 回答
9

如果您使用的是 Eclipse,那么有一个很棒的ASM 插件可以帮助您学习。它将现有 Java 代码显示为检测所述代码所需的实际 ASM 调用。它对于学习非常有用,因为您可以看到实现特定 Java 代码所需的 ASM 调用。

于 2011-03-18T01:11:59.897 回答