0

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.)

Miguel Gamboa
  • 8,855
  • 7
  • 47
  • 94
  • what do you mean by "mediator" method? – vijay Nov 06 '12 at 13:13
  • Imagine that at certain point, my instrumentation engine is intercepting the invocation of the target method: `obj.foo(x)`. So, at this point I replace this call: `obj.foo(x)`, by: `mediator$foo(obj, x)` – in this case the `mediator$foo` is a new static method in the caller class. Therefore, the `mediator$foo(obj, x)` do the stuff that it needs and then it will invoke the target: `obj.foo(x)`. – Miguel Gamboa Nov 07 '12 at 14:54
  • is the mediator method a static or instance method? – vijay Nov 07 '12 at 23:45
  • The mediator is always a static method. – Miguel Gamboa Nov 08 '12 at 12:19

1 Answers1

1

The verifier is correct to reject your code (see JVM specification). There is no way to bypass bytecode verifier.

One way around is to inline the mediator code at the point of constructor invocation. You still can invoke parts of mediator as method calls before or after the invocation of the constructor, but the very constructor invocation has to be in the same method as the new instruction.

Another way is to make special mediators for every class being instantiation, so the mediators invoke the new instruction themselves, along with the constructor call.

You can also look at existing AOP libraries if they can do the required job correctly.

Alexei Kaigorodov
  • 13,189
  • 1
  • 21
  • 38