registerNatives()方法做了什么?
在java中,Object类的私有静态方法registerNatives()
是做什么的?
其他答案在技术上是正确的,但对于没有JNI经验的人来说不是很有用。 🙂
通常,为了让JVMfind你的本地函数,它们必须以某种方式命名。 例如,对于java.lang.Object.registerNatives
,相应的C函数被命名为Java_java_lang_Object_registerNatives
。 通过使用registerNatives
(或者说JNI函数RegisterNatives
),你可以任意命名你的C函数。
这是关联的C代码(来自OpenJDK 6):
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])); }
(请注意, Object.getClass
不在列表中;它仍将由Java_java_lang_Object_getClass
的“标准”名称Java_java_lang_Object_getClass
。)对于列出的函数,关联的C函数在表中列出,这比编写一堆更加容易的转发function。
如果将Javaembedded到C程序中并且想要链接到应用程序内部的函数(而不是在共享库中),或者所使用的函数没有被“导出”,注册本机函数也很有用,因为这些函数通常不会被标准的方法查找机制find。 注册本地函数也可用于将本地方法“重新绑定”到另一个C函数(例如,如果您的程序支持dynamic加载和卸载模块,则可用)。
我鼓励大家阅读JNI书 ,这个书谈到了这个以及更多。 🙂
可能有点混淆的是,在前面的回答中为java.lang.Object.registerNatives
显示的代码仅仅是如何注册本地函数的一个例子 。 这是(在OpenJDK的实现中)为类Object注册本地函数的代码。 要为您自己的类注册本地函数,您必须从您自己的库中的本机代码中调用JNI函数RegisterNatives
。 这可能听起来有些循环,但有几个方法可以打破循环。
-
按照类Object的这个实现的例子:
一个。 在你的Java类中,声明一个名为
registerNatives
的本地方法(最好是静态方法)(或者其他任何名字,没关系)。湾 在您的本地代码中,定义一个名为
Java_<your fully qualified class name>_registerNatives
,其中包含对JNI函数RegisterNatives
的调用。C。 确保在您的Java代码中,在调用其他本地方法之前调用Java
registerNatives
方法。
要么
-
使用
JNI_OnLoad
一个。 在您的本地库中定义一个函数
jint JNI_OnLoad(JavaVM *vm, void *reserved)
。 在这个函数的主体中,调用JNI函数RegisterNatives
。湾 当您的本地库被
System.loadLibrary
加载时,Java VM将自动查找并调用JNI_OnLoad
,您应该已经调用了它,可能是在您的类的静态初始化程序中。 (通过调用vm
指针指向的表中的GetEnv
函数,获得所需的env
指针。)
既然你看了源代码find它,这很容易猜到是不是?
这是一个本地方法,它被称为registerNatives,所以我想它注册对象与底层平台。
这也是私人的,所以可能没什么可担心的。