Library that allows easy printing of bytecode inst

2019-06-25 10:06发布

问题:

I am looking for a library that will easily allow me to see a method's given bytecode. Example:

ALOAD 0
INVOKEVIRTUAL ns/c.m ()I
IRETURN

I've tried both:

  • ASM : I could actually get it to print instructions plus parameters, but I'm having difficulties wrapping my head around its whole visitors paradigm, that is to say, the best I did was to pretty print a whole class.
  • BCEL : Could get it to print the instructions, but no parameters.
  • JavaAssist : Could get it to print the instructions, but no parameters.

回答1:

Take a look at the ASM source for TraceClassVisitor and TraceMethodVisitor for an example of printing bytecode details.

Here's a simple test class:

import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.util.TraceClassVisitor;

public class Main {
    public static void main(String[] args) throws Exception {
        if (1 > args.length) {
            System.err.println("No arguments.");
            return;
        }
        InputStream is = Main.class.getResourceAsStream(args[0]);
        ClassReader cr = new ClassReader(is);
        cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), 0);
    }
}

Which outputs (when passed Main.class as an argument):

// class version 50.0 (50)
// access flags 0x21
public class Main {

  // compiled from: Main.java

  // access flags 0x1
  public <init>()V
   L0
    LINENUMBER 11 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x9
  public static main([Ljava/lang/String;)V throws java/lang/Exception 
   L0
    LINENUMBER 13 L0
    ICONST_1
    ALOAD 0
    ARRAYLENGTH
    IF_ICMPLE L1
   L2
    LINENUMBER 14 L2
    GETSTATIC java/lang/System.err : Ljava/io/PrintStream;
    LDC "No arguments."
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L3
    LINENUMBER 15 L3
    RETURN
   L1
    LINENUMBER 17 L1
   FRAME SAME
    LDC LMain;.class
    ALOAD 0
    ICONST_0
    AALOAD
    INVOKEVIRTUAL java/lang/Class.getResourceAsStream (Ljava/lang/String;)Ljava/io/InputStream;
    ASTORE 1
   L4
    LINENUMBER 18 L4
    NEW org/objectweb/asm/ClassReader
    DUP
    ALOAD 1
    INVOKESPECIAL org/objectweb/asm/ClassReader.<init> (Ljava/io/InputStream;)V
    ASTORE 2
   L5
    LINENUMBER 19 L5
    ALOAD 2
    NEW org/objectweb/asm/util/TraceClassVisitor
    DUP
    NEW java/io/PrintWriter
    DUP
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    INVOKESPECIAL java/io/PrintWriter.<init> (Ljava/io/OutputStream;)V
    INVOKESPECIAL org/objectweb/asm/util/TraceClassVisitor.<init> (Ljava/io/PrintWriter;)V
    ICONST_0
    INVOKEVIRTUAL org/objectweb/asm/ClassReader.accept (Lorg/objectweb/asm/ClassVisitor;I)V
   L6
    LINENUMBER 28 L6
    RETURN
    MAXSTACK = 6
    MAXLOCALS = 3
}


回答2:

Out of those, ASM is the only one supporting the latest Java version. In regards to visitors, you may want to read this tutorial. It been written for an older version of ASM API, but visitor concepts are still the same.