2011-03-18 72 views
10

我已经开始搞乱了我正在编译的一个编译器项目的ASM API。然而,我发现许多地方的文档对于新手来说都不是很清楚,我认为有一个很好的例子来生成一个简单打印“Hello,World!”的类。这将是一个很好的例子。生成'Hello,World!'类与Java ASM库

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

  • 包含一个main()
  • 创建一个本地字符串在main()与变量的值,“你好,世界!”
  • 打印变量

回答

13

您可以使用Java编译一个类,然后让ASM打印出来,将采取产生的等价类的调用,

FAQ

ASMifierClassVisitor

的ASMifierClassVisitor就的javadoc居然有个招呼世界代码,

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 plugin,将有助于你的学习。它将现有的Java代码显示为实际所需的ASM调用来处理所述代码。这是非常有用的学习,因为您可以看到实现特定Java代码所需的ASM调用。

+2

我更关心ASM API调用来生成字节码,但我无论如何,这肯定会检查出来。 – seadowg 2011-03-18 01:28:08