Привет мир! Программа, использующая JAVA ASM для отображения байт-кода

Я не могу отображать байт-коды на моем экране. Я хочу генерировать выходные данные, подобные 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, но мой код сейчас не компилируется, я получаю такие исключения; Исключение в потоке «основной» 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. не могли бы вы помочь мне в отладке этого кода? я реализовал текстификатор, но кажется, что он запрашивает объект массива строк в основном методе. Я попытался преобразовать путь к файлу класса, но это не сработало. Не могли бы вы помочь здесь?

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

    }

person Prathako    schedule 28.01.2013    source источник


Ответы (2)


если вы хотите, чтобы вывод выводился на экран, а не в файл, замените

ClassWriter cw=new ClassWriter(0);

с участием

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

и заменить

this.WriteClass(cw);

с участием

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

см. Javadoc TreeClassVisitor и измените свой код соответственно.

person mantrid    schedule 28.01.2013
comment
эй, я разместил свой код. Не могли бы вы помочь в отладке, пожалуйста? - person Prathako; 31.01.2013

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 обычно работает, когда вы указываете точный абсолютный путь к файлу класса, байт-код которого вас интересует. Я пытался увидеть, работает ли он с относительным путем, но, похоже, это не так.

Вывод (инструкции байт-кода) распечатывается на стандартный вывод.

Кроме того, jar, который я использую для Textifier, - это asm-util-4.0.jar, поэтому не забудьте включить его в путь сборки.

person vijay    schedule 28.01.2013
comment
эй, обычно это работает, когда вы указываете точный абсолютный путь к файлу класса, байт-код которого вас интересует. Я пытался увидеть, работает ли он с относительным путем, но это не так. Я обновил ответ, чтобы отразить это более четко. Кроме того, было бы полезно, если бы вы могли сказать мне, что именно не работает. это не дает вам желаемого результата или просто ничего не делает? - person vijay; 29.01.2013
comment
Я не могу использовать Textifier. Это конкретно для какой-то банки??? мы можем использовать непосредственно, как вы использовали его? или нам нужно взять объект или что-то?? - person Prathako; 29.01.2013
comment
да... поэтому jar, который я использую... asm-util-4.0.jar. и конкретный оператор импорта снова import org.objectweb.asm.util.Textifier;, я сделал обновления для фактического ответа, чтобы отразить то же самое. - person vijay; 29.01.2013