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 。 这可能听起来有些循环,但有几个方法可以打破循环。

  1. 按照类Object的这个实现的例子:

    一个。 在你的Java类中,声明一个名为registerNatives的本地方法(最好是静态方法)(或者其他任何名字,没关系)。

    湾 在您的本地代码中,定义一个名为Java_<your fully qualified class name>_registerNatives ,其中包含对JNI函数RegisterNatives的调用。

    C。 确保在您的Java代码中,在调用其他本地方法之前调用Java registerNatives方法。

要么

  1. 使用JNI_OnLoad

    一个。 在您的本地库中定义一个函数jint JNI_OnLoad(JavaVM *vm, void *reserved) 。 在这个函数的主体中,调用JNI函数RegisterNatives

    湾 当您的本地库被System.loadLibrary加载时,Java VM将自动查找并调用JNI_OnLoad ,您应该已经调用了它,可能是在您的类的静态初始化程序中。 (通过调用vm指针指向的表中的GetEnv函数,获得所需的env指针。)

既然你看了源代码find它,这很容易猜到是不是?

这是一个本地方法,它被称为registerNatives,所以我想它注册对象与底层平台。

这也是私人的,所以可能没什么可担心的。