ASM: output di bytecode e opcode java

Sto cercando di scrivere un programma che prende un file .class e raccoglie tutti i metodi del file .class, nonché i contenuti di ciascun metodo. Ecco il mio codice

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

e qui è la mia uscita

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

In definitiva non voglio stampare questi valori, voglio solo poterli consultare nel mio programma (sto cercando di verificare che stia ottenendo i valori corretti). Sto ottenendo i metodi come previsto, ma il contenuto dei metodi non ha senso per me. Come vedo io questi non sono opcode; in particolare “fffffff” non è un codice operativo java. Quello che mi piacerebbe fare è stampare tutti i metodi come ho fatto sopra e poi dove ho ora gli opcode, stampare il bytecode java seguito da alcuni spazi e poi l’opcode. Per esempio

 main bytecode ** . . 

Il file che sto caricando in questo programma consiste solo di un metodo principale, una singola istruzione println e un’inizializzazione di una variabile int.

La mia domanda allora è che sto facendo qualcosa di sbagliato, o sto semplicemente interpretando i miei risultati correttamente? Inoltre, come posso ottenere il bytecode? Non sono stato in grado di trovare un modo per ottenerlo. Posso vederlo quando uso il plugin jtec bytecode outline per eclipse, ma ho bisogno di poterlo fare riferimento nel mio programma.

    Grazie in anticipo

    Sono stato in grado di capirlo da solo. Sto postando la mia soluzione nel caso in cui qualcun altro abbia lo stesso problema. Si noti che nella mia implementazione qui non sto stampando gli opcode (una sola istruzione println è tutto ciò che deve essere aggiunto per fare ciò).

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

    e qui è l'output che viene prodotto

      L0 LINENUMBER 1 L0 ALOAD 0 INVOKESPECIAL java/lang/Object. ()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