我正在寻找一个库,将容易让我看到一个方法的给定字节码。例子:
ALOAD 0
INVOKEVIRTUAL ns/c.m ()I
IRETURN
我都试过了:
- ASM:我实际上可以让它打印指令和参数,但是我很难理解它的整个访问者范式,也就是说,我所做的最好的是打印整个类。
- BCEL:可以让它打印指令,但没有参数。
- JavaAssist:可以让它打印指令,但没有参数
查看TraceClassVisitor
和TraceMethodVisitor
的ASM源代码,以获得打印字节码细节的示例。
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);
}
}
当传递Main.class
作为参数时,输出:
// 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
}
其中ASM是唯一支持最新Java版本的。关于访问者,您可能需要阅读本教程。它是为ASM API的旧版本编写的,但是访问者的概念仍然相同。