使用 Java ASM 库生成“Hello, World!”类

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

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

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

答案 1

您可以使用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();
  }
}

答案 2

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


推荐