2 Stimmen

Java ASM Hilfe benötigen

Ich schreibe ein einfaches Programm mit Java ASM, um den Bytecode zu generieren, der durch Kompilieren der folgenden Klasse erzeugt wird.

public class Main {
    public static void main(String[] args) {
        System.out.println("Test");
    }
}

Der Code, den ich geschrieben habe, um den Bytecode für diese Klasse zu erzeugen, ist unten angegeben.

public class CodeGenerator {

    public void generateClass()
    {
        ClassWriter cw=new ClassWriter(Opcodes.NULL);
        FieldVisitor fv;
        MethodVisitor mv;
        cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Main", null, "java/lang/Object", null);
        mv=cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitVarInsn(Opcodes.AALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
        mv=cw.visitMethod(Opcodes.ACC_PUBLIC+ Opcodes.ACC_STATIC, "Main", "([Ljava/lang/String;)V", null, null);
        mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream");
        mv.visitLdcInsn("Test");
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(2, 1);
        mv.visitEnd();
        cw.visitEnd();
        this.WriteClass(cw);
    }
    public void WriteClass(ClassWriter cw){
        FileOutputStream fos;
        try{
            fos = new FileOutputStream("E:\\Acadamic\\Final year project\\ASM\\Main.class");
            fos.write(cw.toByteArray());
            fos.close();
        }
        catch (IOException ex){
            Logger.getLogger(CodeGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

Die Kompilierung war erfolgreich, und wenn ich versuche, sie auszuführen, wird folgende Fehlermeldung angezeigt.

Exception in thread "main" java.lang.NoClassDefFoundError: main/class
Caused by: java.lang.ClassNotFoundException: main.class
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: main.class.  Program will exit.

Kann mir jemand bitte helfen, diesen Fehler zu vermeiden. Wenn jemand die Ursache des Fehlers erklären kann und wie man ihn vermeiden kann, bitte ich um Ihre Hilfe.

Ich danke Ihnen.

Nachbereitung:

Wenn ich es wie Java Main ausführe, gibt es die folgende Fehlermeldung.

Exception in thread "main" java.lang.ClassFormatError: Field "out" in class Main
 has illegal signature "Ljava/io/PrintStream"
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClassCond(Unknown Source)
        at java.lang.ClassLoader.defineClass(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access$000(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: Main.  Program will exit.

11voto

Adam Paynter Punkte 45274

Ich glaube nicht, dass Ihr Fehler durch ASM verursacht wird. Es sieht so aus, als hätten Sie einfach java unrichtig. Sie sollten es so nennen:

java Main

Ich vermute, dass Sie es so genannt haben:

java Main.class

更新情報

Es gibt drei Probleme mit Ihrem Code.

Problem Nr. 1

En ClassWriter Konstruktor akzeptiert eine Bitmaske von Optionen. Sie übergeben es Opcodes.NULL . Dies mag zwar scheinen Richtig, Sie wollen es tatsächlich weitergeben 0 ( Opcodes.NULL bedeutet etwas anderes).

ClassWriter cw=new ClassWriter(0);

Problem Nr. 2

Sie rufen an AALOAD im Konstruktor anstelle von ALOAD . Die AALOAD Anweisung lädt eine Feldelement in der Erwägung, dass ALOAD lädt eine lokale Variable .

mv.visitVarInsn(Opcodes.ALOAD, 0);

Problem Nr. 3

In Ihrem Main Methode, haben Sie das Semikolon nach Ljava/io/PrintStream :

mv.visitFieldInsn(
    Opcodes.GETSTATIC,
    "java/lang/System",
    "out",
    "Ljava/io/PrintStream;" // Notice the semicolon
  );

Sie können sich einige Schmerzen ersparen, indem Sie die Vorteile von ASM nutzen Type Klasse:

mv.visitFieldInsn(
    Opcodes.GETSTATIC,
    "java/lang/System",
    "out",
    Type.getObjectType("java/io/PrintStream").getDescriptor()
  );

2voto

Codifier Punkte 145

Nur um hinzuzufügen, Durch Erfahrung habe ich festgestellt, dass illegale Signatur Fehler kommt in der Regel durch fehlende Semikolon am Ende der Methode Beschreibung.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X