Java registerNatives()方法做什么?

Java registerNatives()方法做什么?,java,c,object,methods,java-native-interface,Java,C,Object,Methods,Java Native Interface,在java中,对象类的私有静态方法registerNatives()做什么?其他答案在技术上是正确的,但对于没有JNI经验的人来说不是很有用。:-) 通常,为了让JVM找到本机函数,它们必须以某种方式命名。e、 例如,对于java.lang.Object.registerNatives,相应的C函数名为java\u java\u lang\u Object\u registerNatives。通过使用registernations(或者更确切地说,使用JNI函数registernations),

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

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

通常,为了让JVM找到本机函数,它们必须以某种方式命名。e、 例如,对于
java.lang.Object.registerNatives
,相应的C函数名为
java\u java\u lang\u Object\u registerNatives
。通过使用
registernations
(或者更确切地说,使用JNI函数
registernations
),您可以随意命名C函数

下面是相关的C代码(来自OpenJDK 6):

(请注意,
Object.getClass
不在列表中;它仍将被
Java\u Java\u lang\u Object\u getClass
的“标准”名称调用)对于列出的函数,相关的C函数如该表中所列,这比编写一组转发函数更方便

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


我鼓励每个人都阅读这本书,其中谈到了这一点以及更多内容。:-)

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

  • 遵循类对象的此实现示例:

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

    b。在本机代码中,定义一个名为
    Java\uu registerNatives
    的函数,该函数包含对JNI函数
    registerNatives
    的调用

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

  • 使用
    JNI\u OnLoad

    a。在本机库中定义一个函数
    jint JNI\u OnLoad(JavaVM*vm,void*reserved)
    。在此函数体中,调用JNI函数
    RegisterNatives

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


  • 啊,当然,我没有考虑过JNI方面。。。谢谢大家!您编写了完全修饰过的JNI函数名,这让它很混乱:是由VM自动调用的
    Java\u Java\u lang\u Object\u registerNatives
    ,还是c/c++代码必须调用该函数,而不需要所有Javagobblygook@Pavel默认情况下,类
    fully.qualified.ClassName
    中的本机方法
    methodName
    在C-name
    Java\u fully\u-qualified\u-ClassName\u-methodName
    下搜索(您的C-side代码必须导出)。您可以调用
    JNIEnv
    RegisterNatives
    方法来覆盖此链接。换句话说,如果你不先使用
    registernations
    ,“所有的java GobblyBook”[sic]都是必需的。啊,好吧,那么通过只导出一个函数
    java\u java\u lang\u Object\u registernations
    ,我实际上可以通过检查
    cls
    的值来链接我所有的JNI内容。我错过了RegisterNaties实际上是java本身的一部分这一部分。所以当某个类即将被使用时,JVM用来链接本机的操作顺序是什么?看起来,如果本地人还没有注册(来自c/c++),JVM会检查所有这些导出的名称,如果它们不存在,那么它会尝试使用Object.registerNatives(或者其他方法?)。顺便说一句,jni book链接已失效。如果您尚未调用
    注册表项
    ,并且导出的名称不可用,则在尝试调用该方法时将出现运行时错误
    Object.registerNatives
    是OpenJDK实现
    java.lang.Object
    的内部方法,从其类初始化器调用,其唯一目的是注册仅属于
    java.lang.Object
    的本机方法。如果您正在编写自己的本机库,则由您自己注册库的本机方法(如果您愿意)。
    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]));
    }