2

我正在尝试编写一个程序,该程序采用 .class 文件并收集 .class 文件的所有方法以及每个方法的内容。这是我的代码

public class ClassReaderTest1 {

    public static void main(String[] args) throws Exception{
        InputStream in = new FileInputStream("*.class");
        ClassReader reader = new ClassReader(in);
        ClassNode classNode = new ClassNode();
        reader.accept(classNode,0);
        @SuppressWarnings("unchecked")
        final List<MethodNode> methods = classNode.methods;

        for(MethodNode m: methods){
             InsnList inList = m.instructions;
             System.out.println(m.name);
             for(int i = 0; i< inList.size(); i++){
                 System.out.println("     " +     Integer.toHexString(inList.get(i).getOpcode()));
             }
        }
    }
}

这是我的输出

init>
     ffffffff
     ffffffff
     19
     b7
     b1
     ffffffff
main
     ffffffff
     ffffffff
     b2
     12
     b6
     ffffffff
     ffffffff
     3
     36
     ffffffff
     ffffffff
     b1
     ffffffff

最终我不想打印这些值,我只想能够在我的程序中引用它们(我试图检查我是否得到了正确的值)。我得到了预期的方法,但方法的内容对我来说没有意义。在我看来,这些不是操作码;特别是“fffffff”不是java操作码。我想做的是打印出我上面所做的所有方法,然后在我现在有操作码的地方打印出 java 字节码,然后是几个空格,然后是操作码。例如

main
    bytecode **
    .
    .

我加载到这个程序中的文件只包含一个 main 方法、一个 println 语句和一个 int 变量的初始化。

那么我的问题是我做错了什么,还是我没有正确解释我的结果?另外,我怎样才能得到字节码?我一直无法找到获得它的方法。当我使用eclipse的java字节码大纲插件时可以看到它,但我需要能够在我的程序中引用它。

提前致谢

4

1 回答 1

17

我能够自己弄清楚。我正在发布我的解决方案,以防其他人遇到同样的问题。请注意,在我的实现中,我没有打印出操作码(只需添加一个 println 语句即可)。

import java.io.InputStream;
import java.io.FileInputStream;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.util.List;
import org.objectweb.asm.*;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.util.*;

public class ClassReaderTest1 {

    public static void main(String[] args) throws Exception{
        InputStream in = new FileInputStream("*afile*");
        ClassReader reader = new ClassReader(in);
        ClassNode classNode = new ClassNode();
        reader.accept(classNode,0);
        @SuppressWarnings("unchecked")
        final List<MethodNode> methods = classNode.methods;
        for(MethodNode m: methods){
             InsnList inList = m.instructions;
             System.out.println(m.name);
             for(int i = 0; i< inList.size(); i++){
                 System.out.print(insnToString(inList.get(i)));
             }
        }
    }

    public static String insnToString(AbstractInsnNode insn){
        insn.accept(mp);
        StringWriter sw = new StringWriter();
        printer.print(new PrintWriter(sw));
        printer.getText().clear();
        return sw.toString();
    }

    private static Printer printer = new Textifier();
    private static TraceMethodVisitor mp = new TraceMethodVisitor(printer); 

}

这是产生的输出

<init>
   L0
    LINENUMBER 1 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
main
   L2
    LINENUMBER 3 L2
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "Hello World!!!"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L3
    LINENUMBER 4 L3
    ICONST_0
    ISTORE 1
   L4
    LINENUMBER 5 L4
    RETURN
   L5
于 2013-10-04T05:20:34.733 回答