Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 允许轻松打印字节码指令*包括*参数的库_Java_Reflection_Bytecode - Fatal编程技术网

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

Java 允许轻松打印字节码指令*包括*参数的库,java,reflection,bytecode,Java,Reflection,Bytecode,我正在寻找一个库,它可以轻松地让我看到一个方法的给定字节码。例如: ALOAD 0 INVOKEVIRTUAL ns/c.m ()I IRETURN 我两个都试过了: ASM:实际上,我可以让它打印指令和参数,但我很难理解它的整个访问者范式,也就是说,我所做的最好的工作就是漂亮地打印整个类 BCEL:可以让它打印指令,但没有参数 JavaAssist:可以让它打印指令,但没有参数 其中,ASM是唯一支持最新Java版本的。对于访客,您可能需要阅读。它是为旧版本的ASM API编写的,但是访问

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

ALOAD 0
INVOKEVIRTUAL ns/c.m ()I
IRETURN
我两个都试过了:

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

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

请查看源代码,以获取打印字节码详细信息的示例

下面是一个简单的测试类:

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时):

//类版本50.0(50)
//访问标志0x21
公共班机{
//编译自:Main.java
//访问标志0x1
公共()V
L0
线路号11 L0
阿洛德0
调用特定的java/lang/Object。()V
返回
MAXSTACK=1
最大局部数=1
//访问标志0x9
publicstaticmain([Ljava/lang/String;)V抛出java/lang/Exception
L0
线路号13 L0
ICONST_1
阿洛德0
排列长度
IF_ICMPLE L1
L2
行号14 L2
GETSTATIC java/lang/System.err:Ljava/io/PrintStream;
最不发达国家“没有理由”
INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
L3
线路号15 L3
返回
L1
17号线L1
框架相同
LDC LMain;.class
阿洛德0
ICONST_0
AALOAD
InvokeVirtualJava/lang/Class.getResourceAsStream(Ljava/lang/String;)Ljava/io/InputStream;
阿斯托尔1号
L4
线路号18 L4
新建org/objectweb/asm/ClassReader
重复
阿洛德1号
调用特殊的org/objectweb/asm/ClassReader(Ljava/io/InputStream;)V
阿斯托尔2号
L5
线路号19 L5
阿洛德2号
新建org/objectweb/asm/util/TraceClassVisitor
重复
新的java/io/PrintWriter
重复
GETSTATIC java/lang/System.out:Ljava/io/PrintStream;
调用特殊的java/io/PrintWriter。(Ljava/io/OutputStream;)V
调用特殊的org/objectweb/asm/util/TraceClassVisitor。(Ljava/io/PrintWriter;)V
ICONST_0
INVOKEVIRTUAL org/objectweb/asm/ClassReader.accept(Lorg/objectweb/asm/ClassVisitor;I)V
L6
线路号28 L6
返回
MAXSTACK=6
最大局部变量=3
}

谢谢你的链接,但我已经读过了。它解释了ASM访问者工作原理背后的基本概念,而且它确实是生成新方法/执行基本指令所需的一切。另一方面,它不能帮助我理解如何按照我想要的方式实际操作一台像样的打印机。“字节码转换”部分有一个序列图也适用于您的案例。您使用的是TraceClassVisitor,而不是ClassWriter。其他一切都是一样的。访问者从以前的事件生成器(例如ClassReader或以前的访问者)接收事件序列并且可以改变事件的顺序。所以,如果跟踪访问者没有收到特定的事件类型,它将不会打印出来。你猜不到,但这不是闹着玩的!听起来你找到了解决方案。
// 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
}