允许轻松打印字节码指令*包括*参数的库

发布于 2024-12-13 23:25:46 字数 287 浏览 0 评论 0原文

我正在寻找一个库,它可以轻松地让我查看方法的给定字节码。示例:

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

我已经尝试了两种方法:

  • ASM :我实际上可以让它打印指令和参数,但是我很难理解它的整个访问者范例,也就是说,我所做的最好的就是漂亮地打印一个全班。
  • BCEL:可以让它打印指令,但没有参数。
  • JavaAssist:可以让它打印指令,但没有参数。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萌面超妹 2024-12-20 23:25:46

查看 ASM 源代码 TraceClassVisitorTraceMethodVisitor 查看打印字节码详细信息的示例。

这是一个简单的测试类:

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
}

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
}
牵强ㄟ 2024-12-20 23:25:46

其中,ASM 是唯一支持最新 Java 版本的。对于访问者,您可能需要阅读本教程。它是为旧版本的 ASM API 编写的,但访问者概念仍然相同。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文