2014-05-06 7 views
7

Ich bin neu in ASM und ich möchte etwas Hilfe im Zusammenhang mit Bytecode-Transformation.Hinzufügen von Try/Catch-Block in Bytecode durch ASM

Frage: Ich möchte Try/catch-Block für die gesamte Methode in Bytecode über ASM hinzufügen und möchte die Methode ohne Verwendung von Java-Option -Overify ausführen. Ich kann try/catch-Block für die gesamte Methode hinzufügen, aber wenn ich versuchte, die Methode auszuführen, bekomme ich 'java.lang.VerifyError'. Wenn ich die Option java -noverify verwende, wird sie ausgeführt. Bitte hilf mir.

Unten sind die Details.

Ich möchte den obigen Code wie unten vorstellen, um Try/Catch-Blöcke mit ASM-Bytecode-Instrumentierung einzuführen.

Unter dem Code fügen Sie try/catch block hinzu, aber führt den Code nicht mit der Option java -noverify aus.

Für das Debugging habe ich CheckClassAdapter verwendet und ich habe unten Verifizierungsproblem bekommen.

Message:org.objectweb.asm.tree.analysis.AnalyzerException: Execution can fall off end of the code 
    at org.objectweb.asm.tree.analysis.Analyzer.findSubroutine(Unknown Source) 
    at org.objectweb.asm.tree.analysis.Analyzer.findSubroutine(Unknown Source) 
    at org.objectweb.asm.tree.analysis.Analyzer.analyze(Unknown Source) 
    at org.objectweb.asm.util.CheckClassAdapter.verify(Unknown Source) 
    at org.objectweb.asm.util.CheckClassAdapter.verify(Unknown Source) 
    at com.mfr.instrumentation.selenium.work.InstrumentExample.main(InstrumentExample.java:166) 
hello()V 
00000 ?  : L0 
00001 ?  :  GETSTATIC java/lang/System.out : Ljava/io/PrintStream; 
00002 ?  :  LDC "Hello world" 
00003 ?  :  INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V 
00004 ?  :  RETURN 
00005 ?  : L1 
00006 ?  :  GOTO L2 
00007 ?  : L3 
00008 ?  :  ASTORE 2 
00009 ?  :  ALOAD 2 
00010 ?  :  INVOKEVIRTUAL java/lang/Exception.printStackTrace()V 
00011 ?  : L2 
    TRYCATCHBLOCK L0 L1 L3 java/lang/Exception 

Ich konnte die obige Bestätigungsnachricht nicht verstehen.

+0

Was ist die Frage? – biziclop

+0

Frage ist, wie kann ich meinen ursprünglichen Code mit out versuchen/catch Block zu meinem letzteren Code mit try/catch-Block mit ASM Bytecode Instrumentierung. –

Antwort

4

Die obige Ausnahme bezieht sich auf Stackmap-Datenblöcke. ASM hat einen Mechanismus bereitgestellt, um Stackmap-Frames selbst bereitzustellen. Wir müssen das Parameter-Flag als COMPUTE_FRAMES im ClassWriter-Konstruktor verwenden.

Beispiel: ClassWriter cw = neuer ClassWriter (ClassWriter.COMPUTE_FRAMES);

public static final int COMPUTE_FRAMES Flag zur automatischen Berechnung der Stack-Map-Frames von Methoden von Grund auf neu. Wenn dieses Flag gesetzt ist, werden die Aufrufe der Methode MethodVisitor.visitFrame (int, int, java.lang.Object [], int, java.lang.Object []) ignoriert, und die Stack-Map-Frames werden von der Methode neu berechnet Methoden Bytecode. Die Argumente der Methode visitMaxs werden ebenfalls ignoriert und aus dem Bytecode neu berechnet. Mit anderen Worten, computeFrames impliziert computeMaxs.

von ASM ClassWriter API.

5

Sie müssen Ihre Klasse durchlaufen und eine modifizierte MethodVisitor in den Prozess verwenden. Wenn Sie Ihre gesamte Methode in ein try - catch Konstrukt verpacken. Sie können dies tun, indem Sie das Konstrukt einfügen, indem Sie die Rückrufe für den Anfang und das Ende des Aufrufblocks abfangen. Diese Methoden sind visitCode und visitEnd, die Sie so abfangen konnte:

class MyMethodVisitor extends MethodVisitor { 
    // constructor omitted 

private final Label start = new Label(), 
        end = new Label(), 
        handler = new Label(); 

    @Override 
    public void visitCode() { 
    super.visitCode(); 
    visitTryCatchBlock(start, 
     end, 
     handler, 
     "java/lang/Exception"); 
    visitLabel(start); 
    } 

    @Override 
    public void visitEnd() { 
    visitJumpInsn(GOTO, end); 
    visitLabel(handler); 
    visitMethodInsn(INVOKEVIRTUAL, 
     "java/lang/RuntimeException", 
     "printStackTrace", 
     "()V"); 
    visitInsn(RETURN); 
    visitLabel(lCatchBlockEnd); 
    super.visitEnd(); 
    } 
} 

Beachten Sie jedoch, dass dieses Beispiel nicht Stapel Kartenrahmen enthält, die Sie hinzufügen müssen, wenn Sie Byte-Code für Java 7+ produzieren.

Beachten Sie jedoch, dass diese Lösung am Anfang der Ausnahmetabelle Ihrer Methode einen dominanten Handler registriert, der alle anderen try-catch-finally-Blöcke in Ihrer Methode überschreibt, die bereits vorhanden sind!

+0

Ich habe Ihre Vorschläge implementiert und kann erfolgreich try/catch-Block für die gesamte Methode hinzufügen. Ich habe es dekompiliert und verifiziert. Aber als ich diese Methode ausführen wollte, bekomme ich 'java.lang.VerifyError'. Wenn ich die Methode mit der Option -noverify ausführe, kann ich die Methode erfolgreich ausführen. Ich habe meine Frage bearbeitet und den Code hinzugefügt, um try/catch hinzuzufügen. Können Sie mir bitte sagen, was ich tun soll, um den Code ohne Verwendung der Option -noverify auszuführen. –

+0

Was sagt der Prüfer? Und welche Java-Version verwendest du? Wie ich in meiner Antwort gesagt habe, müssen Sie möglicherweise einen Stapel Kartenrahmen stapeln. Asm kann sie für Sie berechnen. –

+0

Gerade habe ich die Frage mit Verifier Nachricht aktualisiert. Ich benutze Java 7 Version. und ASM 5.0.2 jar –