你好,世界!使用JAVA ASM编程显示字节码

时间:2013-01-28 03:12:28

标签: java opcode java-bytecode-asm

我无法在屏幕上显示字节码。我想为hello World生成类似Javap Command的输出。

我创建了以下类和hello world类。任何人都可以让我知道我要做什么来生成字节码,我做错了什么?

        **package com.gannon.ASMInterpreterMain;**

            import java.io.FileOutputStream;
            import java.io.IOException;

            import org.objectweb.asm.ClassWriter;
            import org.objectweb.asm.FieldVisitor;
            import org.objectweb.asm.MethodVisitor;
            import org.objectweb.asm.Opcodes;

            public class CodeGenerator {

                public void generateClass()
                {
                    ClassWriter cw=new ClassWriter(0);
                    FieldVisitor fv;
                    MethodVisitor mv;
                    cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, "com/gannon/ASMInterpreterMain/HelloWorldOutPut", null, "java/lang/Object", null);
                    mv=cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
                    mv.visitVarInsn(Opcodes.ALOAD, 0);
                    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
                    mv.visitInsn(Opcodes.RETURN);
                    mv.visitMaxs(1, 1);
                    mv.visitEnd();
                    mv=cw.visitMethod(Opcodes.ACC_PUBLIC+ Opcodes.ACC_STATIC, "Main", "([Ljava/lang/String;)V", null, null);
                    mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
                    mv.visitLdcInsn("Test");
                    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
                    mv.visitInsn(Opcodes.RETURN);
                    mv.visitMaxs(2, 1);
                    mv.visitEnd();
                    cw.visitEnd();
                    this.WriteClass(cw);
                }
                public void WriteClass(ClassWriter cw){
                    FileOutputStream fos;
                    try{
                        fos = new FileOutputStream("C:\\Users\\Anish\\workspace\\ASMProject\\Main.class");
                        fos.write(cw.toByteArray());
                        fos.close();
                    }
                    catch (IOException ex){

                        System.out.println("Error: "+ex.getMessage());
                        //Logger.getLogger(CodeGenerator.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }

                public static void main (String [] args){

                    CodeGenerator CG = new CodeGenerator();
                    CG.generateClass();

                }
            }

我尝试使用tracefilevisitor,但我的代码现在没有编译,我得到像这样的例外; 线程“main”中的异常java.lang.IncompatibleClassChangeError:实现类     请有人帮我吗

      package com.gannon.ASMInterpreterMain;

        import java.io.PrintWriter;

        import org.objectweb.asm.ClassWriter;
        import org.objectweb.asm.MethodVisitor;
        import org.objectweb.asm.Opcodes;
        import org.objectweb.asm.util.TraceClassVisitor;

        public class CodeGenerator {

            public void generateClass() {
                ClassWriter cw = new ClassWriter(0);
                TraceClassVisitor tc = new TraceClassVisitor(
                        new PrintWriter(System.out));
                MethodVisitor mv;
                tc.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC,
                        "com/gannon/ASMInterpreterMain/HelloWorldOutPut", null,
                        "java/lang/Object", null);
                mv = tc.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
                mv.visitVarInsn(Opcodes.ALOAD, 0);
                mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>",
                        "()V");
                mv.visitInsn(Opcodes.RETURN);
                mv.visitMaxs(1, 1);
                mv.visitEnd();
                mv = tc.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "Main",
                        "([Ljava/lang/String;)V", null, null);
                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out",
                        "Ljava/io/PrintStream;");
                mv.visitLdcInsn("Test");
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream",
                        "println", "(Ljava/lang/String;)V");
                mv.visitInsn(Opcodes.RETURN);
                mv.visitMaxs(2, 1);
                mv.visitEnd();
                tc.visitEnd();
                byte [] b = cw.toByteArray();

                System.out.println(b.length);
                for (int i = 1; i < b.length; i++) {
                    System.out.println(b[i]);
                }

            }

        //  public void WriteClass(ClassWriter cw) {
        //      FileOutputStream fos;
        //      try {
        //          fos = new FileOutputStream(
        //                  "C:\\Users\\Anish\\workspace\\ASMProject\\Main.class");
        //          fos.write(cw.toByteArray());
        //          fos.close();
        //      } catch (IOException ex) {
        //
        //          System.out.println("Error: " + ex.getMessage());
        //          //Logger.getLogger(CodeGenerator.class.getName()).log(Level.SEVERE, null, ex);
        //      }
        //  }

            //public static void main (String [] args){

            //  CodeGenerator CG = new CodeGenerator();
            //  CG.generateClass();

            //}

            public static void main(String[] args) throws Exception {
                //        String pathToClassFile = "C:\\Users\\Anish\\workspace\\ASMProject\\Main.class";
                //      Textifier.main(pathToClassFile);

                CodeGenerator CG = new CodeGenerator();
                 CG.generateClass();
            }
        }
  

您好,   我尝试实现你曾经问过的概念,但我的代码仍然没有用,   我在这里附加我的代码,我想运行以显示我的操作码   helloworld计划。你可以帮我调试一下这段代码吗?我实施了   textifier但似乎它在main方法中要求字符串数组对象。我试过转换   我的类文件路径,但它没有工作。你能帮忙吗?

     package com.gannon.ASMInterpreterMain;

    import java.io.PrintWriter;
    import org.objectweb.asm.util.Textifier;
    import org.objectweb.asm.ClassWriter;
    import org.objectweb.asm.MethodVisitor;
    import org.objectweb.asm.Opcodes;
    import org.objectweb.asm.util.TraceClassVisitor;

    public class CodeGenerator {

        public void generateClass() {
            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
            TraceClassVisitor tc = new TraceClassVisitor( cw,
                    new PrintWriter(System.out));
            MethodVisitor mv;
            tc.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC,
                    "com/gannon/ASMInterpreterMain/HelloWorldOutPut", null,
                    "java/lang/Object", null);
            mv = tc.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>",
                    "()V");
            mv.visitInsn(Opcodes.RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
            mv = tc.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "Main",
                    "([Ljava/lang/String;)V", null, null);
            mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out",
                    "Ljava/io/PrintStream;");
            mv.visitLdcInsn("Test");
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream",
                    "println", "(Ljava/lang/String;)V");
            mv.visitInsn(Opcodes.RETURN);
            mv.visitMaxs(2, 1);
            mv.visitEnd();
            tc.visitEnd();
            byte [] b = cw.toByteArray();

            System.out.println(b.length);
            for (int i = 1; i < b.length; i++) {
                System.out.println(b[i]);
            }

        }

        public static void main (String [] args){

              String[] pathToClassFile = {"com/gannon/ASMInterpreterMain/HelloWorldOutPut"};
                try {
                    Textifier.main(pathToClassFile);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    System.out.println("Excption thrown from main is "+e.getMessage());
                }
        }

    }

2 个答案:

答案 0 :(得分:2)

如果您希望将输出打印在屏幕上而不是打印到文件中,则替换

ClassWriter cw=new ClassWriter(0);

TraceClassVisitor cw = new TraceClassVisitor(new PrintWriter(System.out));

并替换

this.WriteClass(cw);

cw.print(new PrintWriter(System.out));

请参阅TreeClassVisitor javadoc并相应修改您的代码。

答案 1 :(得分:0)

import org.objectweb.asm.util.Textifier;

public class ByteCodeReader {
        public static void main(String[] args) throws Exception {
        String pathToClassFile = "<path to classfile of interest goes here>";
        Textifier.main(pathToClassFile);
    }
}

所以当你给出你感兴趣的字节码的类文件的确切绝对路径时,Textifier通常会起作用。我试图看看它是否与相对路径一起工作,但似乎没有。

输出(字节代码指令)打印到标准输出。

另外,我用于Textifier的jar是asm-util-4.0.jar,所以不要忘记在构建路径中包含它。