2

基本的には、メソッドの最後に単純なSystem.out.println("hey"); を追加しようとしています。私はツリーAPIを使用しました。しかし私はこのエラーを取得しておくん:asm javaを使用しているときの検証エラーの取得

java.lang.VerifyError: Expecting a stackmap frame at branch target 38

は、これは私のコードです:

public class MethodNodeCustom extends MethodNode { 

    public MethodNodeCustom(int paramInt, String paramString1, String paramString2, String paramString3, String[] paramArrayOfString) { 
     this(327680, paramInt, paramString1, paramString2, paramString3, paramArrayOfString); 
     return; 
    } 

    @SuppressWarnings({ "unchecked", "rawtypes" }) 
    public MethodNodeCustom(int paramInt1, int paramInt2, String paramString1, String paramString2, String paramString3, 
     String[] paramArrayOfString) { 
     super(paramInt1); 
     this.access = paramInt2; 
     this.name = paramString1; 
     this.desc = paramString2; 
     this.signature = paramString3; 
     this.exceptions = new ArrayList((paramArrayOfString == null) ? 0 : paramArrayOfString.length); 
     int i = ((paramInt2 & 0x400) != 0) ? 1 : 0; 
     if (i == 0) 
      this.localVariables = new ArrayList(5); 
     this.tryCatchBlocks = new ArrayList(); 
     if (paramArrayOfString != null) 
      this.exceptions.addAll(Arrays.asList(paramArrayOfString)); 
     this.instructions = new InsnList(); 
    } 
    @Override 
    public void visitEnd() { 
     AbstractInsnNode label = instructions.getLast(); 
     instructions.remove(instructions.getLast()); 
     instructions.remove(instructions.getLast()); 
     visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", Type.getDescriptor(PrintStream.class)); 
     visitLdcInsn("Cracked by damm ass pro skills"); 
     visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); 
     visitInsn(Opcodes.RETURN); 
     instructions.add(label); 

     super.visitEnd(); 
    } 
} 

そして、これは私のクラスのノードである:

public class ClassNodeCustom extends ClassNode { 
    public ClassNodeCustom() { 
     super(ASMContentHandler.ASM4); 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    public MethodVisitor visitMethod(int paramInt, String paramString1, String paramString2, String paramString3, String[] paramArrayOfString) { 
     MethodNode localMethodNode = new MethodNodeCustom(paramInt, paramString1, paramString2, paramString3, paramArrayOfString); 
     this.methods.add(localMethodNode); 
     return localMethodNode; 
    } 
} 

そして、これは私が「注入」する方法ですコード(私はそれがzipファイルを使用しているなぜjar thatsから直接ロードする)

そして、これまで実行したときに私が言ったように、私は検証エラーが出てきました。それを解決する方法はありますか?

答えて

5

メソッドの最後にコードを追加する場合、最後の命令の後に追加します。最後の命令は、Javaコードのコンパイル時に常にgoto、switch、throwまたはreturn文です。

void foo() { } 

のような明示的なreturn文なしでメソッドをコンパイルする場合でも、最終的なリターンが暗黙的であるどこactully

void foo() { return; } 

をコンパイルしています。あなたの追加を使用すると、

void foo() { 
    return; 
    System.out.println("hey"); 
} 
に方法を変更するような到達不能コードをバイトコードで のjavacが、完全に合法で禁止されています。到達不能なコードの場合は、スタックの状態とその時点でのローカル変数配列を記述する stack map frameを前置する必要があります。この時点では、空のフレームの説明を追加するだけでも簡単ですが、return文の前にコードを追加すると仮定します。

ASM offers an AdviceAdapterこれを実装するには、return文の前にコードを追加することができます。私が知る限り、ツリーAPIには何も似ていませんが、メソッドの命令リスト内のリターンノードを探し、その前にコードを追加することができます。

+0

この行は、リターンを削除するために使用されます。命令と最後のラベルとそれらをreaded AbstractInsnNode label = instructions.getLast(); instructions.remove(instructions.getLast()); instructions.remove(instructions.getLast()); – NacOJerk

+0

私はそれを試してみました – NacOJerk

+0

最後のテストで何らかの理由で私の問題が見つかったので、メソッドの最後にcertinコードを追加する必要がありました。私はうんざりして戻りコードを二度追加したようなものです。 – NacOJerk

関連する問題