ASM: вывод Java-байт-кода и кода операции

Я пытаюсь написать программу, которая принимает файл.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 **
    .
    .

Файл, который я загружаю в эту программу, состоит только из основного метода, одного оператора println и инициализации переменной int.

У меня вопрос: я делаю что-то не так или просто неправильно интерпретирую свои результаты? Кроме того, как я могу получить байт-код? Я не смог найти способ получить это. Я вижу это, когда использую подключаемый модуль java bytecode для затмения, но мне нужно иметь возможность ссылаться на него в моей программе.

заранее спасибо

1 ответ

Решение

Я смог понять это самостоятельно. Я публикую свое решение на тот случай, если у кого-то возникнет такая же проблема. Обратите внимание, что в моей реализации я не распечатываю коды операций (для этого нужно добавить только один оператор 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
Другие вопросы по тегам