Java asmiger不';显示得不够

Java asmiger不';显示得不够,java,java-bytecode-asm,Java,Java Bytecode Asm,我试图使用asmiger来准确地理解.class文件中的内容。问题是该工具忽略了某些mv.visitXXX。例如,它不会为行声明标签显示mv.visitLabel(标签) 这是有意义的,因为asmiger只显示创建类所需的mv.visit,但我希望以不同的方式使用它 是否有必要要求工具显示它访问的所有内容?对于与源代码行关联的标签,在asmizer中没有条件处理,换句话说,如果ClassReader报告它们,asmizer将显示它们 要使其工作,必须满足两个条件: 该方法必须具有与其code属性

我试图使用asmiger来准确地理解.class文件中的内容。问题是该工具忽略了某些mv.visitXXX。例如,它不会为行声明标签显示mv.visitLabel(标签)

这是有意义的,因为asmiger只显示创建类所需的mv.visit,但我希望以不同的方式使用它


是否有必要要求工具显示它访问的所有内容?

对于与源代码行关联的标签,在
asmizer
中没有条件处理,换句话说,如果
ClassReader
报告它们,asmizer将显示它们

要使其工作,必须满足两个条件:

  • 该方法必须具有与其
    code
    属性关联的
    LineNumberTable
    属性(对于普通类,这是由生成
    .class
    文件时使用的编译器选项驱动的)

  • 您不能指定
    ClassReader的
    accept
    方法的
    SKIP_DEBUG

  • 使用
    javac
    时,调试信息的存在与否由
    -g
    选项控制。默认设置是生成
    LineNumberTable
    属性,因此不指定
    -g
    选项已经足够了。那么下面的程序

    package bytecodetests;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import org.objectweb.asm.ClassReader;
    import org.objectweb.asm.util.ASMifier;
    import org.objectweb.asm.util.TraceClassVisitor;
    
    public class BytecodeTests {
    
      public static void main(String[] args) throws IOException {
        new ClassReader(BytecodeTests.class.getResourceAsStream("BytecodeTests.class"))
          .accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(System.out)), 0);
      }
    
    }
    
    将产生

    package asm.bytecodetests;
    import java.util.*;
    import org.objectweb.asm.*;
    public class BytecodeTestsDump implements Opcodes {
    
    public static byte[] dump () throws Exception {
    
    ClassWriter cw = new ClassWriter(0);
    FieldVisitor fv;
    MethodVisitor mv;
    AnnotationVisitor av0;
    
    cw.visit(52, ACC_PUBLIC + ACC_SUPER, "bytecodetests/BytecodeTests", null, "java/lang/Object", null);
    
    cw.visitSource("BytecodeTests.java", null);
    
    {
    mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
    mv.visitCode();
    Label l0 = new Label();
    mv.visitLabel(l0);
    mv.visitLineNumber(9, l0);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
    mv.visitInsn(RETURN);
    Label l1 = new Label();
    mv.visitLabel(l1);
    mv.visitLocalVariable("this", "Lbytecodetests/BytecodeTests;", null, l0, l1, 0);
    mv.visitMaxs(1, 1);
    mv.visitEnd();
    }
    {
    mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, new String[] { "java/io/IOException" });
    mv.visitCode();
    Label l0 = new Label();
    mv.visitLabel(l0);
    mv.visitLineNumber(12, l0);
    mv.visitTypeInsn(NEW, "org/objectweb/asm/ClassReader");
    mv.visitInsn(DUP);
    mv.visitLdcInsn(Type.getType("Lbytecodetests/BytecodeTests;"));
    mv.visitLdcInsn("BytecodeTests.class");
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getResourceAsStream", "(Ljava/lang/String;)Ljava/io/InputStream;", false);
    mv.visitMethodInsn(INVOKESPECIAL, "org/objectweb/asm/ClassReader", "<init>", "(Ljava/io/InputStream;)V", false);
    mv.visitTypeInsn(NEW, "org/objectweb/asm/util/TraceClassVisitor");
    mv.visitInsn(DUP);
    mv.visitInsn(ACONST_NULL);
    mv.visitTypeInsn(NEW, "org/objectweb/asm/util/ASMifier");
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESPECIAL, "org/objectweb/asm/util/ASMifier", "<init>", "()V", false);
    mv.visitTypeInsn(NEW, "java/io/PrintWriter");
    mv.visitInsn(DUP);
    mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
    mv.visitMethodInsn(INVOKESPECIAL, "java/io/PrintWriter", "<init>", "(Ljava/io/OutputStream;)V", false);
    mv.visitMethodInsn(INVOKESPECIAL, "org/objectweb/asm/util/TraceClassVisitor", "<init>", "(Lorg/objectweb/asm/ClassVisitor;Lorg/objectweb/asm/util/Printer;Ljava/io/PrintWriter;)V", false);
    mv.visitInsn(ICONST_0);
    Label l1 = new Label();
    mv.visitLabel(l1);
    mv.visitLineNumber(13, l1);
    mv.visitMethodInsn(INVOKEVIRTUAL, "org/objectweb/asm/ClassReader", "accept", "(Lorg/objectweb/asm/ClassVisitor;I)V", false);
    Label l2 = new Label();
    mv.visitLabel(l2);
    mv.visitLineNumber(14, l2);
    mv.visitInsn(RETURN);
    Label l3 = new Label();
    mv.visitLabel(l3);
    mv.visitLocalVariable("args", "[Ljava/lang/String;", null, l0, l3, 0);
    mv.visitMaxs(8, 1);
    mv.visitEnd();
    }
    cw.visitEnd();
    
    return cw.toByteArray();
    }
    }
    
    调用
    main
    方法



    当从命令行运行
    asmiger
    时,它确实默认使用
    SKIP_DEBUG
    标志,除非
    -DEBUG
    选项已作为第一个参数给出。

    谢谢我在命令行使用asmiger工具:java-cp“asm-all-5.1.jar”org.objectweb.asm.util.asmfoo.class>Foo.asm但您的解决方案非常适合我的需要。
    Label l0 = new Label();
    mv.visitLabel(l0);
    mv.visitLineNumber(12, l0);
    …
    Label l1 = new Label();
    mv.visitLabel(l1);
    mv.visitLineNumber(13, l1);
    …
    Label l2 = new Label();
    mv.visitLabel(l2);
    mv.visitLineNumber(14, l2);
    …