2010-12-05 12 views
1

Ich habe in die ASM-Bibliothek gesucht. Zuerst schrieb ich ein Programm, um eine Hallo-Weltklasse zu erstellen, und dann dachte ich, ich würde etwas komplizierteres ausprobieren, eine Klasse erstellen, die einen PythonInterpreter (Teil der Jython-Bibliothek) erstellt und eine Python-Datei ausführt. Das Ergebnis ist das folgende, leider bekomme ich die Ausnahme, die ich diese Frage nannte, nachdem ich versuche, die resultierende Klasse auszuführen.java.lang.VerifyError: (Klasse: Main, Methode: Hauptsignatur: ([Ljava/lang/String;) V) Stack zu groß

public class Main { 
public static void main(String[] args) { 
    String mainFile = "main.py"; 

    ClassWriter mainClass = new ClassWriter(ClassWriter.COMPUTE_MAXS); 
    mainClass.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "Main", null, "java/lang/Object", null); 
    MethodVisitor mainMethod = mainClass.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null); 

    mainMethod.visitTypeInsn(Opcodes.NEW, "org/python/util/PythonInterpreter"); 
    mainMethod.visitMethodInsn(Opcodes.INVOKESPECIAL, "org/python/util/PythonInterpreter", "<init>", "()V"); 

    mainMethod.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); 
    mainMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/python/util/PythonInterpreter", "setOut", "(Ljava/io/PrintStream;)V"); 
    mainMethod.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;"); 
    mainMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/python/util/PythonInterpreter", "setErr", "(Ljava/io/PrintStream;)V"); 

    mainMethod.visitLdcInsn(mainFile); 
    mainMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/python/util/PythonInterpreter", "execFile", "(Ljava/lang/String;)V"); 
    mainMethod.visitInsn(Opcodes.RETURN); 

    mainMethod.visitEnd(); 
    mainClass.visitEnd(); 

    try{ 
     byte[] b = mainClass.toByteArray(); 
     FileOutputStream writer = new FileOutputStream("Main.class"); 
     writer.write(b); 
     writer.close(); 
    }catch(IOException e){ 
     e.printStackTrace(); 
    } 
} 

}

+0

Wenn Sie Code auf höherer Ebene wie diesen schreiben, könnten Sie etwas wie JavaSist leichter finden als ASM. Du machst einfach einen String aus Java-Code und gibst ihn Javessist zum kompilieren. Erspart Ihnen das effektive Erlernen aller Bytecode-Operationen und das Verwalten der Stacks usw.. Ich bin immer davon überzeugt, dass ASM eher ein Werkzeug für Compilerautoren ist. – dty

+0

Mein Problem war, dass ich VisitMaxs nicht aufgerufen habe, bevor ich meinen Methodenbesuch beendet habe. Aber jetzt bekomme ich Beschwerden wegen eines leeren Stapels, der anscheinend entdeckt wurde. – user405163

+0

Versuchen Sie, Ihren Code mit dem Flag "-noverify" auszuführen. Dies sollte Ihnen helfen, das Problem zu lokalisieren –

Antwort

1

Wenn Sie zu den setOut und setErr Methoden kommen, müssen Sie nur ein Argument, und kein Objekt auf die Methode aufzurufen. (Der Aufruf an "verzehrte" das initialisierte Objekt!)

Gleiches gilt für den Aufruf an execFile. Sie haben ein Argument (mainFile), aber kein Objekt, das execFile aufgerufen werden kann.

Versuchen Sie, drei DUP Anweisungen nach NEW hinzuzufügen. (Um genügend Referenzen für die drei Methodenaufrufe zu speichern, die Sie für dieses Objekt ausführen möchten.)