2013-10-03 3 views
2

Je suis en train d'écrire un programme qui prend un fichier .class et rassemble toutes les méthodes du fichier .class ainsi que le contenu de chaque méthode. Voici mon codeASM: sortie bytecode java et opcode

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

et voici ma sortie

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

En fin de compte, je ne veux pas imprimer ces valeurs, je veux juste être en mesure de les référencer dans mon programme (je suis essayer de vérifier que je reçois les bonnes valeurs). Je reçois les méthodes comme prévu mais le contenu des méthodes n'a pas de sens pour moi. Comme je le vois ce ne sont pas des opcodes; en particulier "fffffff" n'est pas un opcode java. Ce que je voudrais faire est d'imprimer toutes les méthodes comme je l'ai fait ci-dessus et où je les opcodes maintenant, imprimer le bytecode java suivi de quelques espaces, puis l'opcode. Par exemple

main 
    bytecode ** 
    . 
    . 

Le fichier que je chargeais dans ce programme se compose de seulement une méthode principale, une seule instruction println, et une initialisation d'une variable int.

Ma question est alors que je fais quelque chose de mal, ou suis-je tout simplement pas mes résultats interprète correctement? En outre, comment puis-je obtenir le bytecode? Je n'ai pas réussi à trouver un moyen de l'obtenir. Je peux le voir quand j'utilise le plugin contour bytecode java pour Eclipse, mais je dois être en mesure de faire référence dans mon programme.

Merci d'avance

Répondre

10

J'ai été capable de le découvrir par moi-même. Je poste ma solution au cas où quelqu'un d'autre aurait le même problème. Notez que dans ma mise en œuvre ici, je ne suis pas en train d'imprimer les opcodes (une instruction println est tout ce qui doit être ajouté à le faire).

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

} 

et voici la sortie qui est produit

<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 
+0

Pour ce que ça vaut la peine, la magie de ClassReader est fourni par http://asm.ow2.org/doc/faq.html Je crois – balupton