I am working on a bytecode instrumentation project. Currently when handling objects, the verifier throws an error most of the time. So I would like to get things clear concerning rules with objects (I read the JVMS but couldn't find the answer I was looking for):
I am instrumenting the NEW instruction:
original bytecode
NEW <MyClass>
DUP
INVOKESPECIAL <MyClass.<init>>
after instrumentation
NEW <MyClass>
DUP
INVOKESTATIC <Profiler.handleNEW>
DUP
INVOKESPECIAL <MyClass.<init>>
Note that I added a call to Profiler.handleNEW() which takes as argument an object reference (the newly created object).
The piece of code above throws a VerificationError. While if I don't add the INVOKESTATIC (leaving only the DUP), it doesn't. So what is the rule that I'm violating? I can duplicate an uninitialized reference but I can't pass it as parameter? I would appreciate any help. Thank you
The JVM verifier treats an object whose constructor has yet to be called as if it had a special compile-time type called "uninitialized".
So what's happening from the verifier's point of view is that you are passing the wrong type of object as the first parameter to Profiler.handleNEW()
, because "uninitialized" is not considered a subclass of Object (so to speak).
The relevant part of the JVM spec regarding how "uninitialized" is defined is here.