之前舉了一個簡單的JNI demo。
我們回顧一下:
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("", "");
}
}
這裏就產生一個問題。Foo.java中的bar方法怎麼就知道調用到那個c方法呢?
我們通過javac -h Foo.java命令生成了一個.h文件,我們注意下這個文件裏的方法名:Java_diveinjvm_Foo_bar
這裏可以看出,方法名以Java_開頭+包名_+類名_+方法名。
這種情況屬於 Java 虛擬機自動查找符合默認命名規範的 C 函數。
還要一個情況:
我們看下java.lang.Object這個類有很多native方法比如:
public native int hashCode();
並且Object類開頭有一段代碼
private static native void registerNatives();
static {
registerNatives();
}
registerNatives方法應該也對應一個c方法。
查看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]));
}
這裏對hashCode進行了註冊。這樣調用Object類中的hashCode就能調用到
openjdk\openjdk8\openjdk\jdk\src\share\native\java\lang\Object.c中的JVM_IHashCode方法。