I need to instrument native methods to make a simple static call before executing normally. Because the methods are native, I have to use the "setNativePrefix" feature and wrap the native methods with an intermediate call with the original method signature.
After what I thought was a simple bytecode change to accomplish this, I'm getting a StackOverflowError right before the wrapper method gets executed even though the stack is basically empty. Here's my test class:
public class SimpleTest {
public static void main(String[] args) throws IOException {
Perf.getPerf().highResCounter();
}
}
Normally, that program would produce nothing on the console. However, my instrumented bytecode executes a println() before executing the native method $wrapper$highResCounter(). This can be seen in the relevant Perf class bytecode after instrumentation:
public long highResCounter() {
getstatic PrintStream System.out
ldc String Constant "this is an instrumented println"
invokevirtual void PrintStream.println(String)
aload 0
invokevirtual long Perf.$wrapped$highResCounter()
lreturn
}
public native long $wrapped$highResCounter();
I'm sort of new to Java bytecode, so I probably made a mistake here. Here's the output of the program, which shows that the println() gets executed, but somewhere after the first invokevirtual call a StackOverflowError is thrown:
this is an instrumented println call
Exception in thread "main" java.lang.StackOverflowError
at com.foo.SimpleTest.main(SimpleTest.java:17)
What could be causing this StackOverflowError? And how do I fix it?