使用Java ASM库生成一个"Hello, World!"类

14

我开始尝试使用ASM API来进行编译器项目的开发。然而,对于初学者来说,文档在很多地方不够清晰,因此我认为要在这里提供一个打印 "Hello, World!" 的类的良好实例是非常重要的。

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

  • 含有main()方法
  • 在main()方法中创建一个名为"Hello, World!"的本地字符串变量
  • 打印变量
2个回答

17
你可以使用Java编译一个类,然后使用ASM打印出生成等效类所需的调用。 常见问题解答 ASMifierClassVisitor ASMifierClassVisitor的Javadoc实际上包含了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();
  }
}

9
如果您正在使用Eclipse,有一个很棒的ASM插件可以帮助您学习。它将现有的Java代码显示为实际的ASM调用,以便于对代码进行插桩。它非常有用,因为您可以看到实现特定Java代码所需的ASM调用。

2
我更关注ASM API调用以生成字节码,但无论如何我一定会检查这个的。 - seadowg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接