Question

I am trying to write a Java agent library that is loaded dynamically via attach api to retransform some methods (those that appear in stack traces of certain threads) for recording method entry/exit. The method entry/exit information is then exported via a custom MBean.

My current "prototype" works so far, as long as the instrumented methods are not native.

According to the documentation of java.lang.instrument.Instrumentation#setNativeMethodPrefix(), it should be possible for java agents to replace the native method with a non-native stub method and add another native method with that prefix in its name which is then bound to the original native method's native code.

However, when implementing this, I get this error:

java.lang.UnsupportedOperationException: class redefinition failed: attempted to add a method

which is right since I added the new native method.

Only replacing the native method with a non-native one works, but then I cannot delegate the call back to the original native method. Defining the native method in another class does nor work since native methods are looked up by class name and method name and there is no nativeMethodClassSuffix or similar. Defining another class with the same name in another new classloader would work, and I think it might be possible with some indirections to delegate the call to the new class, but one native library can only be linked to native methods loaded by classes of only one class loader, so I won't get the native methods linked properly.

Is there anything obvious I'm missing here? My code is a bit too long to post here, if anyone thinks it helps I can try to build a small example java agent that shows the problem and link to it here.

Was it helpful?

Solution

Is there anything obvious I'm missing here? My code is a bit too long to post here, if anyone thinks it helps I can try to build a small example java agent that shows the problem and link to it here.

No. If you mask out a native method, there is no longer any way to call it from JNI. You need to call the method using native code. (I have not idea what that is, but I would be surprised if it is not possible)

Another option is to change all the references to the native method instead of mask it out. That way you can still call the original method when you choose to.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top