I want to add instructions to the code of methods. These instructions should be executed after reaching and before leaving the method.
In order to make sure that the latter instructions are always executed before leaving I want to put these in a finally block.
(I know the class AdviceAdapter but it does not ensure the execution of exit-code when an invoked method throws an exception.)
My problem is that the instructions in the result are in the wrong order.
Method to be processed:
@Test
public void original() {
assertTrue(true);
assertTrue(!(false));
}
Desired result:
@Test
public void desired() {
//some logging X
try {
assertTrue(true);
assertTrue(!(false));
}
finally {
//some logging Y
}
}
(logging X can also take place in the first line of the try block.)
(The bytecode of the desired result is equal to the bytecode of the following Java code:)
@Test
public void desired() {
//some logging X
try {
assertTrue(true);
assertTrue(!(false));
//some logging Y
}
catch (Throwable t) {
//some logging Y
throw t;
}
}
I found the problem:
The existing code is not inserted in the visitCode method when invoking super.visitCode. This method is empty in the super class. That makes clear the existing code is added at some other point.
Solution:
I invoke my method before (which adds the code for the new lines which need to be at the beginning) in the visitCode method. I invoke after in visitVarInsn if the opcode is an return statement.
@Override
public void visitCode()
{
before();
}
@Override
public void visitInsn(int opcode)
{
if (OpcodesUtil.isXRETURN(opcode))
{
after();
}
super.visitInsn(opcode);
}
(The AdviceAdapter had worked too, but there were some problems ensuring that every ClassReader's accept method is invoked with EXPAND_FRAMES. Furthermore, it might advice more exit points and that does not work when closing exactly one try block.)
他のヒント
I'm not sure where the error is in your approach. But I achieved something like this after a bit of trial and error using AdviceAdapter.