registerNatives()
是做什么用的?registerNatives()
是做什么用的?java.lang.Object.registerNatives
,相应的C函数的名称为Java_java_lang_Object_registerNatives
。通过使用registerNatives
(或者更准确地说是JNI函数RegisterNatives
),您可以将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]));
}
(请注意,Object.getClass
不在列表中;它仍将被“标准”名称Java_java_lang_Object_getClass
所调用。) 对于列出的函数,相关的C函数在该表中如上所述,这比编写一堆转发函数更方便。
如果您将Java嵌入到C程序中并希望链接到应用程序本身内部的函数(而不是链接到共享库中的函数),或者正在使用的功能没有被“导出”,则注册本机功能也很有用,因为这些通常无法通过标准方法查找机制找到。注册本机函数还可以用于将本机方法“重绑定”到另一个C函数(例如,如果您的程序支持动态加载和卸载模块,则非常有用)。
我鼓励每个人阅读JNI书籍,其中讨论了这个问题以及更多内容。 :-)
Java_java_lang_Object_registerNatives
是由VM自动调用的,还是c/c++代码必须调用该函数,而且没有必要使用所有那些java术语。 - Pavel Pfully.qualified.ClassName
中的本地方法methodName
将在C名称Java_fully_qualified_ClassName_methodName
下搜索(您的C端代码必须导出)。您可以调用JNIEnv
的RegisterNatives
方法来覆盖此链接。换句话说,如果您不先使用RegisterNatives
,则需要“所有那些Java胡言乱语”[sic]。 - C. K. YoungJava_java_lang_Object_registerNatives
,我实际上可以通过检查 cls
的值来链接所有我的 JNI 东西。我错过了 registerNatives 实际上是 Java 自身的一部分的那部分。那么...当某个类即将被使用时,JVM 使用哪些操作顺序来链接本地方法?似乎如果本地方法尚未注册(来自 c/c++),则 JVM 将检查所有这些导出名称,如果它们不存在,则尝试使用 Object.registerNatives(或者反之亦然?)。顺便说一下,jni 书籍链接已经失效了。 - Pavel PRegisterNatives
,并且导出的名称不可用,则在尝试调用该方法时会出现运行时错误。 Object.registerNatives
是OpenJDK对java.lang.Object
的实现的内部方法,从其类初始化程序中调用,其唯一目的是注册与java.lang.Object
相关的本机方法。 如果您正在编写自己的本机库,则需要自己注册库的本机方法(如果您希望这样做)。 - C. K. Youngjava.lang.Object.registerNatives
的代码只是注册本地函数的示例。 这是(在OpenJDK的实现中)为Object类注册本地函数的代码。 要为您自己的类注册本机函数,必须从您自己库中的本机代码调用JNI函数RegisterNatives
。 这听起来可能有点循环,但有几种方法可以打破这个循环。
a. 在您的Java类中,声明一个名为registerNatives
(或其他任何名称,不要紧)的本机方法(最好是静态的)。
b. 在您的本地代码中,定义一个名为Java_<your fully qualified class name>_registerNatives
的函数,其中包含对JNI函数RegisterNatives
的调用。
c. 确保在您的Java代码中,在调用其他本机方法之前调用了您的Java registerNatives
方法。
或者
JNI_OnLoad
a. 在您的本机库中定义一个函数jint JNI_OnLoad(JavaVM * vm,void * reserved)
。 在此函数的主体中,调用JNI函数RegisterNatives
。
b. 当通过System.loadLibrary
加载您的本机库时,Java VM将自动寻找并调用JNI_OnLoad
,您应该已经在调用它,可能是在类的静态初始化器中。(您可以通过在vm
指针指向的表中调用GetEnv
函数来获取所需的env
指针。)
它被用于以下场景:
C或C++作为主机,Java JVM作为客户端。 (C加载jvm.dll
并使用JNI_CreateJavaVM
创建JVM)
当Java代码需要调用主机的C函数时,
如果仍然使用jni dll (System.loadLibrary("foo.dll");
)绑定本地java方法,则dll的内存空间与C主机不同。 (如果调用的函数是主机状态无关的,则仍然可以工作,但是您无法以此方式访问主机的状态值)
在这里,您需要在主机上使用env->RegisterNatives()
将主机的C函数注入(绑定、公开、导出)到JVM中。