ASM: outputting java bytecode and opcode

丶灬走出姿态 提交于 2020-01-11 07:07:26

问题


I am trying to write a program that takes a .class file and collects all the methods of the .class file as well as the contents of each method. Here is my code

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()));
             }
        }
    }
}

and here is my output

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

Ultimately I don't want to print these values, I just want to be able to reference them in my program (I'm trying to check that I'm getting the right values). I am getting the methods as expected but the contents of the methods aren't making sense to me. As I see it these are not opcodes; in particular "fffffff" is not a java opcode. What I would like to do is print out all the methods as I have done above and then where I have the opcodes now, print out the java bytecode followed by a few spaces and then the opcode. For example

main
    bytecode **
    .
    .

The file that I am loading into this program consists of only a main method, a single println statement, and an initialization of a int variable.

My question then is am I doing something wrong, or am I just not interpreting my results correctly? In addition, how can I get the the bytecode? I haven't been able to find a way to get it. I can see it when I use the java bytecode outline plugin for eclipse, but I need to be able to reference it in my program.

Thanks in advance


回答1:


I was able to figure it out on my own. I'm posting my solution in case anyone else has the same problem. Note that in my implementation here I am not printing out the opcodes (one println statement is all that needs to be added to do this).

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); 

}

and here is the output that is produced

<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


来源:https://stackoverflow.com/questions/19152526/asm-outputting-java-bytecode-and-opcode

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!