在java中,Object类的私有静态方法registerNatives()
做了什么?
答案 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
。这可能听起来有点圆,但有几种方法可以打破循环。
按照类Object的实现示例:
一个。在Java类中,声明一个名为registerNatives
的本机方法(最好是静态的)(或任何其他名称。这没关系)。
湾在您的本机代码中,定义一个名为Java_<your fully qualified class name>_registerNatives
的函数,该函数包含对JNI函数RegisterNatives
的调用。
℃。确保在Java代码中,在调用其他本机方法之前调用Java registerNatives
方法。
OR
使用JNI_OnLoad
一个。在本机库中定义函数jint JNI_OnLoad(JavaVM *vm, void *reserved)
。在此函数的主体中,调用JNI函数RegisterNatives
。
湾当您的本机库由JNI_OnLoad
加载时,Java VM将自动查找并调用System.loadLibrary
,您应该已经调用了该文件,可能是在您的类的静态初始化程序中。 (通过调用env
指针指向的表中的GetEnv
函数,可以获得所需的vm
指针。)