在Java中,registerNatives()
Object类的private静态方法有什么作用?
Answers:
其他答案在技术上是正确的,但对于没有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函数如该表中所列,这比编写一堆转发函数要方便。
如果将Java嵌入到C程序中并希望链接到应用程序本身内的功能(而不是共享库内),或者不以其他方式“导出”正在使用的功能,则注册本机功能也很有用。通常不会通过标准方法查找机制找到。注册本机函数还可以用于将本机方法“重新绑定”到另一个C函数(例如,如果您的程序支持动态加载和卸载模块,则很有用)。
我鼓励每个人都阅读JNI书,其中讨论了更多内容。:-)
Java_java_lang_Object_registerNatives
VM自动调用了该函数名,或者c / c ++代码必须调用该函数,并且不需要所有Java gobblygook
methodName
类中的本机方法。您可以调用的方法来覆盖此链接。换句话说,如果您不首先使用,则必须使用“ java gobblygook所有”。fully.qualified.ClassName
Java_fully_qualified_ClassName_methodName
JNIEnv
RegisterNatives
RegisterNatives
Java_java_lang_Object_registerNatives
我实际上可以通过检查的值链接我所有的JNI东西cls
。我错过了registerNatives实际上是Java本身的一部分。所以...当要使用某个类时,JVM用来链接本机的动作顺序是什么?看来,如果尚未注册本机(从c / c ++),则JVM会检查所有这些导出的名称,如果不存在,则尝试使用Object.registerNatives(或者相反)。顺便说一句,jni图书链接已失效。
RegisterNatives
,并且导出的名称不可用,则在尝试调用该方法时会出现运行时错误。Object.registerNatives
是OpenJDK实现的内部方法,java.lang.Object
从其类初始化程序调用,其唯一目的是注册java.lang.Object
仅与本机方法有关的方法。如果您正在编写自己的本机库,则要由您自己注册库的本机方法(您希望这样做)。
可能有点令人困惑的是,java.lang.Object.registerNatives
上一个答案中显示的代码仅是如何注册本机函数的示例。这是(在OpenJDK的实现中)为Object类注册本机函数的代码。要为您自己的类注册本机函数,必须RegisterNatives
从您自己的库中的本机代码调用JNI函数。这听起来可能有点循环,但是有几种方法可以打破循环。
遵循该类Object的实现示例:
一种。在您的Java类中,声明一个命名为registerNatives
(或其他任何名称的无关紧要的)本地方法(最好是静态方法)。
b。在您的本机代码中,定义一个名为的函数Java_<your fully qualified class name>_registerNatives
,其中包含对JNI函数的调用RegisterNatives
。
C。确保在您的Java代码中,registerNatives
在调用其他本机方法之前先调用Java方法。
要么
采用 JNI_OnLoad
一种。在您的本机库中定义一个函数jint JNI_OnLoad(JavaVM *vm, void *reserved)
。在此函数的主体中,调用JNI函数RegisterNatives
。
b。当Java虚拟机JNI_OnLoad
由加载时,Java VM将自动查找并调用System.loadLibrary
,您应该已经在调用它了,可能是在类的静态初始化器中。(您可以env
通过GetEnv
在vm
指针指向的表中调用该函数来获得所需的指针。)