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.
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
}
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.