Now I’ve written an instrumentor, MarkerInlineStrategy
that inlines the respective bytecode snippets for monitorEnter
, monitorExit
, isOldThread
, and setOldThread
. I didn’t limit it to just SyncPointBuffer
, instead I’m currently employing it with a ConditionalStrategy
as decorator that only invokes the decoree if the class to be instrumented happens to be SyncPointBuffer
.
I also did a lot of house cleaning. I removed the parameters of type ChangeCallTargetStrategy
and CreateDecoratorStrategy
from instrumentors that can be invoked from FileInstrumentor
‘s command line interface, and now I also allow zeroary constructors, even though the constructor accepting a MethodHashTableStrategy
is still favored.
I improved the @DoNotInstrument
annotation. It is now possible to specify which instrumentation strategies should not be run. The default still is that no instrumentation is performed at all:
@DoNotInstrument
public class Foo {
...
}
However, the SyncPointBuffer
class now has to be instrumented by the MarkerInlineStrategy
, but may not be instrumented by any of the *Synchronized*
, ObjectCallStrategy
, or AssignObjectIDStrategy
instrumentors. I specify that this way:
@DoNotInstrument(instrumentors =
"\*\*\*.\*Synchronized\*;\*\*\*.ObjectCallStrategy;\*\*\*.AssignObjectIDStrategy")
public class Foo {
...
}
The string is a semicolon-separated list of class name patterns for ClassFileTools.classNameMatches()
.
Furthermore, I’ve just split the “method index” long
transmitted in the CompactSynchronizedBlockDebugStrategy
in a “method index & program counter” value. The method index occupies the upper 32 bit, the program counter where the monitorenter
or monitorexit
instruction was found resides in the lower 32 bit. This fits very well with the JVM’s own limitations. Now it’s possible to exactly pinpoint a monitorenter
or monitorexit
in the modified class files. I have to note that this leads to quite a bit more “bloating”, since every pair of method index-program counter that occurs in a class file will now have to be put in the constant pool (i.e. 0x00010000
and 0x00010001
for a monitorenter; monitorexit; return
method instead of just 0x00000001
), but since this is just for debugging, that’s probably acceptable.
I’m running a few tests now to make sure that the recording stage still works after these relatively extensive modifications, then I have to focus on the replay stage again.
One major item still missing is the compact treatment of wait
, sleep
, notify
, and notifyAll
. That might cause some more headache when it comes to the replay algorithm.
Update
I also need to write an instrumentor that inserts a call to SyncPointBuffer.compactThreadExit
at the end of java.lang.Thread.exit
.
Update
Done.