The instrumentation should actually be pretty easy. I just looked at the bytecode of this class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class Test { public static boolean isOldThread() { return true; } public static void setOldThread() { } public static void main(String[] args) { if (isOldThread()) { // some code } else { setOldThread(); } } } |
and the main method contains these instructions:
GeSHi Error: GeSHi could not find the language jvm (using path /home/dh_8dhf9b/concurrentaffair.org/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
The invokestatic Test.isOldThread()Z
puts the return value on the stack. The ifeq
jumps over the then block if the return value was false
; the goto
in line 4 jumps over the else block if it was true
and the then block has already been executed.
This just needs to be turned into
GeSHi Error: GeSHi could not find the language jvm (using path /home/dh_8dhf9b/concurrentaffair.org/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
The old line 1 gets replaced by the new lines 1 and 2, which get the current thread, and then get its $$$oldThread$$$
field.
The old line 5 gets replaced by the new lines 6 to 8, which put true
on the stack, get the current thread, and then set its $$$oldThread$$$
field.
monitorenter
and monitorexit
are even easier to handle.
GeSHi Error: GeSHi could not find the language jvm (using path /home/dh_8dhf9b/concurrentaffair.org/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
just has to be changed into
GeSHi Error: GeSHi could not find the language jvm (using path /home/dh_8dhf9b/concurrentaffair.org/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Exactly the same applies for monitorexit
. The value on top of the stack isn’t used as first parameter anymore, now it’s directly consumed by the monitorenter
or monitorexit
instruction.