I'm defining a java class from C with the JNI call DefineClass() and then I register the native callbacks for the methods in the class that are native. The class has two static methods, both of which are native. I use RegisterNatives() to register the native functions. Both calls succeed.
But when I reference these native methods from my Java code I get java.lang.UnsatisfiedLinkError myPackage.myClass.myMethod(I)V
But I know that DefineClass returned a class object for myPackage.myClass and I know that myMethod(I)V has been registered as a method on that class.
I get this failure just as it is about to execute main() - where the call to my native method is (for the time being, for testing).
As a test, I tried calling DefineClass twice on the same JNIEnv to see what happened. I get a duplicate class definition error. I've also tried calling FindClass() after defining it and the JNIEnv returns a reference to the defined class.
Thus I'm definity creating the class dynamically, but it fails when I try to refer to its methods.
Any ideas? All input appreciated.
Platform: Windows, 32 bit code on 64 bit XP.
ANSWER
Seems that you cannot define a native method using DefineClass() and call that native method directly from your injected code. You have to have a trampoline method in your injected class (in the form of Java byte codes) that then calls your native methods. Only then will it work. Took me three days to work that out.
Another gotcha is make sure that your injected code is valid. The code I was trying looked valid, but on closer inspection I was pulling a 4 byte sized constant from the constant pool as an operand for an 8 byte instruction. So that failed the verifier. Once that was fixed (and the native trampoline), it all worked.
However to get there through all the various permutations I had to try took 3 days. Felt good when if was working though.