java源码解析——RegisterNatives()方法

在学习JDK的反射机制与底层源码的时候,常常会看到一个私有本地方法private static native void registerNatives();
那么它究竟是做什么的呢?

知识储备

首先你需要了解如下基础知识:

  • 了解C语言或C++语言的基础知识
  • 具备JavaSE的基础
  • 了解Java的JNI技术

registerNatives()介绍

这个方法主要的目的就是为了注册本地的方法,具体怎么注册呢。就是将Java中的本地方法与C或C++语言编写的函数进行映射关联。

在做JNI开发的时候,你可能会使用javah生成头文件。在C代码中include生成的头文件。利用这种方式实现的库,就不需要去做函数映射。
Java JNI实现:

package com.aijiao.test;

public class JNIDemo {
    
    //定义一个方法,该方法在C中实现
    public native void testHello();
    
    public static void main(String[] args){
        //加载C文件
        System.loadLibrary("TestJNI");
        JNIDemo jniDemo = new JNIDemo();
        jniDemo.testHello();
    }

}

利用javah生成的头文件:

#include "com_aijiao_test_JNIDemo.h"
#include <iostream>
#include <stdio.h>

JNIEXPORT void JNICALL Java_com_aijiao_test_JNIDemo_testHello
(JNIEnv *, jobject) {
    printf("this is C++ print");
}

从上面的代码中可以看到,它们之间默认就有一种一一对应的映射协议,这样的JNI就不需要去做注册。只需要在开始阶段加载这个Library文件(windows一般为dll,Linux一般为so)即可。
若您在开发的过程中没有按照这种映射协议去生成Library文件,那么就需要使用registerNatives()来进行注册了。

例如,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]));
}

现在你应该能明白,registerNatives()方法的主要目的就是为了建立JVNM与C语言库交互的映射关系,使JVM可以得到操作系统的支持。这也是Java实现跨平台的主要原理。


java源码解析——RegisterNatives()方法
https://blog.cikaros.top/doc/7a5e4e12.html
作者
Cikaros
发布于
2021年4月26日
许可协议