registerNatives()方法有什么作用?

时间:2009-06-18 03:30:57

标签: java c object methods java-native-interface

在java中,Object类的私有静态方法registerNatives()做了什么?

2 个答案:

答案 0 :(得分:102)

其他答案在技术上是正确的,但对没有JNI经验的人来说不是很有用。 : - )

通常,为了让JVM找到您的本机函数,必须以某种方式命名它们。例如,对于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的“标准”名称调用。)对于列出的函数,关联的C函数如下所列table,比编写一堆转发函数更方便。

如果要在您的C程序中嵌入Java并希望链接到应用程序本身内的函数(而不是在共享库中),或者正在使用的函数没有“导出”,那么注册本机函数也很有用。 ,因为通常不会通过标准方法查找机制找到这些。注册本机函数也可用于将本机方法“重新绑定”到另一个C函数(例如,如果您的程序支持动态加载和卸载模块,则非常有用)。

我鼓励大家阅读JNI book,其中讨论了这个以及更多内容。 : - )

答案 1 :(得分:8)

可能有点令人困惑的是,在前一个答案中为java.lang.Object.registerNatives显示的代码只是如何注册本机函数的示例。这是(在OpenJDK的实现中)为类Object注册本机函数的代码。要为您自己的类注册本机函数,必须从您自己库中的本机代码调用JNI函数RegisterNatives。这可能听起来有点圆,但有几种方法可以打破循环。

  1. 按照类Object的实现示例:

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

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

    ℃。确保在Java代码中,在调用其他本机方法之前调用Java registerNatives方法。

  2. OR

    1. 使用JNI_OnLoad

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

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