2011-03-18 69 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