I've been trying to instrument branch-related code using ASM lib in java. Suppose this is a period of code I want to instrument:
if (true) {
System.out.println("true");
} else {
System.out.println("false");
}
Here is my code for instrumentation:
//put true on stack
mv.visitInsn(Opcodes.ICONST_1);
//create labels
Label elseLabel = new Label();
Label endLabel = new Label();
mv.visitJumpInsn(Opcodes.IFEQ, elseLabel);
// instrument code for the "if" block
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("true");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(elseLabel);
//instrument code for else block
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("false");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
mv.visitLabel(endLabel);
The instrumented byte code can be shown and interpreted correctly with Intellij's own decompiler.
However, the code cannot be run, there is VerifyError

And this is the readable bytecode generated by running "javap -c" command.
public void doSomething1();
Code:
0: aload_0
1: invokevirtual #5 // Method doSomething:()V
4: iconst_1
5: invokestatic #6 // Method org/junit/jupiter/api/Assertions.assertTrue:(Z)V
8: iconst_1
9: ifeq 23
12: getstatic #44 // Field java/lang/System.out:Ljava/io/PrintStream;
15: ldc #46 // String true
17: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
20: goto 31
23: getstatic #44 // Field java/lang/System.out:Ljava/io/PrintStream;
26: ldc #48 // String false
28: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
31: return
}
Could you please help me with that? Thank you!
There is no mistake in adding bytecode. However, it is solved simply by passing ClassWriter.COMPUTE_FRAME rather than ClassWriter.ComputeMaxs.(Thanks Johannes Kuhn and anyone who helped me). And red-flagged VerifyError indicates that (though I don't know).
COMPUTE_MAX seems to work for java5 or earlier.