java - Hello World !使用JAVA ASM显示字节码的程序

标签 java opcode java-bytecode-asm

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

我创建了以下类(class)和 Hello World 类(class)。任何人都可以让我知道我必须做什么才能生成字节码以及我做错了什么吗?

        **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.IncompleteClassChangeError:实现类 有谁可以帮我吗

      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();
            }
        }

Hi, I tried implementing the concept that you had ask but my code is still not working, I am attaching my code here that i want to run to display opcodes for my helloworld program. could you please help me in debugging this code? i implemented textifier but it seems it ask for string array object in main method. I tried converting my class file path but it didn't work. Could you please help here?

     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());
                }
        }

    }

最佳答案

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

ClassWriter cw=new ClassWriter(0);

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

并替换

this.WriteClass(cw);

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

参见TreeClassVisitor javadoc并相应地修改您的代码。

关于java - Hello World !使用JAVA ASM显示字节码的程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14554941/

相关文章:

java - 将 "array var-args"作为参数混淆

Java:如何截取视频和音频流?

java - 尝试创建服务类时出现空指针错误

regex - 正确查找 RPAREN(以实现快速解析)

java - <receiver> 类未注册从同一应用程序发送的隐式 Intent ?

c - 如何从操作码/机器码中获取汇编指令或助记符?

java - 避免 getfield 操作码

java - JVM 语言互操作性

java - 为什么CgLib BeanCopier中有一个无用的(在我看来)dup2

java - 使用 Java ASM 库生成 'Hello, World!' 类