2

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.

mihi
  • 6,507
  • 1
  • 38
  • 48
  • Did you find a solution to your problem? I'm having a similar issue and I'll appreciate to see some reference code. – nadavy Sep 01 '15 at 13:24
  • @nadavy no, I decided to not instrument native methods and document this limitation with a link to this StackOverflow question :) – mihi Sep 01 '15 at 14:33
  • lol. Well, that's a solution :-). Thanks for responding! – nadavy Sep 01 '15 at 14:50
  • 1
    @nadavy you should add `Can-Retransform-Classes: true` to the manifest of your agent and use `retransformClasses` method instead of `redefineClasses` – bedrin Mar 24 '16 at 09:11

1 Answers1

2

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.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • thanks for your answer. I was confused since the native method prefix feature sounded like what I should have been using. Changing all references to the method is not feasible in my situation, as that would require scanning all loaded classes for references. Thanks anyway for the quick response :) – mihi Dec 19 '12 at 15:09