A simple JNI demo was given earlier.
Let's review:
package diveinjvm; public class Foo { // public static native void foo(); // public native void bar(int i, long j); public native void bar(String s, Object o); int i = 0xDEADBEEF; public static void main(String[] args) { try { System.loadLibrary("foo"); } catch (UnsatisfiedLinkError e) { e.printStackTrace(); System.exit(1); } new Foo().bar("", ""); } }
There is a problem here. How does the bar method in Foo.java know which c method to call?
We have generated a. h file through javac -h Foo.java command. Let's pay attention to the method name in this file: Java? Diveinjvm? Foo? Bar
As you can see here, the method name starts with Java + package name + class name + method name.
This is a case where the Java virtual machine automatically finds C functions that conform to the default naming specification.
One more thing:
Let's see that java.lang.Object has many native methods, such as:
public native int hashCode();
And the Object class begins with a piece of code
private static native void registerNatives(); static { registerNatives(); }
The registerNatives method should also correspond to a c method.
View the source code of openJdk, openjdk\openjdk8\openjdk\jdk\src\share\native\java\lang\Object.c
static JNINativeMethod methods[] = { {"hashCode", "()I", (void *)&JVM_IHashCode}, {"wait", "(J)V", (void *)&JVM_MonitorWait}, {"notify", "()V", (void *)&JVM_MonitorNotify}, {"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll}, {"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone}, };
JNIEXPORT void JNICALL Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls) { (*env)->RegisterNatives(env, cls, methods, sizeof(methods)/sizeof(methods[0])); }
The hashCode is registered here. In this way, calling the hashCode in the Object class can call the JVM_IHashCode method in openjdk\openjdk8\openjdk\jdk\src\share\native\java\lang\Object.c.