I am developing an instrumentation engine with ASM and I need to intercept the invocation of methods, which receive parameters of array type. For that purpose I implemented a MethodVisitor
and in its visitMethodInsn
I check if the desc
parameter specifies any parameter of array type. If the target method has no parameters of array type, then I have nothing to do and I insert the original method invocation: super.visitMethodInsn(opcode, owner, name, desc);
On the other hand, if the target method has parameters of array type, then I must perform a specific action for its arguments. The easiest solution I got to access each argument was to invoke a mediator method, with the same descriptor of the target method, and in this mediator I can easily access its parameters (corresponding to the arguments passed to the target method).
Yet, a problem arises when the target method is an instance constructor (<init>
). In Java the new XXX()
is translated to bytecode as follows:
NEW XXX
DUP
INVOKESPECIAL XXXX.<init>()
According to the approach that I explained above, I am moving the INVOKESPECIAL
call into a mediator method and the newly instantiated object is the first argument of this mediator. Yet, the verifier raises an error for this mediator, reporting that the first parameter of the mediator (which will be the first argument of the target method - <init>
) is not an “unitialized object”. More precisely I got the error: Exception in thread "main" java.lang.VerifyError: Expecting to find unitialized object on stack”
.
Once I split the bytecodes NEW
and INVOKESPECIAL
in two different methods, then the verifier claims that the argument passed to the INVOKESPECIAL
has been already initialized.
Any suggestion to work around this problem? (please, do not answer me to avoid the mediator and access directly the arguments in the stack, because it is not simple to duplicate and replace arguments that occupy an arbitrary position in the stack.)