Java 之 native 关键字与 registerNatives 方法

Posted 跨链技术践行者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 之 native 关键字与 registerNatives 方法相关的知识,希望对你有一定的参考价值。

一、native 关键字

   native 的本意是原生的,本地的。

   native 是一个修饰符,只可以用来修饰方法。

   native 修饰的方法,看不见方法体;

   native 修饰的方法,不是用 Java 语言实现的,而是调用了底层 C/C++ 的代码,这些代码为 .dll 文件,让 Java来执行。

   native 关键字是 JNI(Java Native Interface)的重要体现。什么是 JNI ,JNI 是Java调用其他语言(c,c++) 的一种机制。native 关键字修饰的是方法,起声明作用,告诉 JVM 老哥自己去调用这个方法。这个方法的实现在别的语言那里已经实现,我们是看不到源码的。

  使用 native 关键字说明这个方法是原生函数,也就是这个方法是用 C/C++等非Java 语言实现的,并且被编译成了 DLL,由 java 去调用。

  (1)为什么要用 native 方法?

    Java 使用起来非常方便,然而有些层次的任务用 Java 实现起来不容易,或者我们对程序的效率很在意时,问题就来了。例如:有时 java 应用需要与 java 外面的环境交互。这是本地方法存在的主要原因,你可以想想 java 需要与一些底层系
统如操作系统或某些硬件交换信息时的情况。本地方法正是这样一种交流机制:它为我们提供了一个非常简洁的接口,而且我们无需去了解 java 应用之外的繁琐的细节。
 

  (2)native 声明的方法,对于调用者,可以当做和其他 Java 方法一样使用

    一个 native method 方法可以返回任何 java 类型,包括非基本类型,而且同样可以进行异常控制。
    native method 的存在并不会对其他类调用这些本地方法产生任何影响,实际上调用这些方法的其他类甚至不知道它所调用的是一个本地方法。 JVM 将控制调用
本地方法的所有细节。
    如果一个含有本地方法的类被继承,子类会继承这个本地方法并且可以用 java语言重写这个方法(如果需要的话)。

二、本地方法

   Java有两种方法:Java方法和本地方法。Java方法是由Java语言编写,编译成字节码,存储在class文件中。本地方法是由其他语言(比如C,C++,或者汇编)编写的,编译成和处理器相关的机器代码。本地方法保存在动态连接库中,格式是各个平台专有的。Java方法是平台无关的,不过本地方法却不是。运行中的Java程序调用本地方法时,虚拟机装载包含这个本地方法的动态库,并调用这个方法。本地方法是联系Java程序和底层主机操作系统的连接方法。

三、registerNatives 本地方法

  1、registerNatives本地方法的作用是什么?

    registerNatives 方法

1 private static native void registerNatives();
2 static 
3     registerNatives();
4 

    从上面的代码中看到Object类定义了一个静态初始化块,我们知道当创建Java对象时,系统总是先调用静态初始化块

    在上面的静态初始化块中调用了registerNatives()方法,并且使用了private来修饰,表面这个方法是私有的并不被外部调用。

    本地方法的实现是由其他语言编写并保存在动态连接库中,因而在java类中不需要方法实现。registerNatives本质上就是一个本地方法,但这又是一个有别于一般本地方法的本地方法,从方法名我们可以猜测该方法应该是用来注册本地方法的。事实上,上述代码的功能就是先定义了registerNatives()方法,然后当该类被加载的时候,调用该方法完成对该类中本地方法的注册。

    registerNatives函数前面有native关键字修饰,Java中,用native关键字修饰的函数表明该方法的实现并不是在Java中去完成,而是由C/C++去完成,并被编译成了.dll,由Java去调用。方法的具体实现体在dll文件中,对于不同平台,其具体实现应该有所不同。用native修饰,即表示操作系统,需要提供此方法,Java本身需要使用。具体到registerNatives()方法本身,其主要作用是将C/C++中的方法映射到Java中的native方法,实现方法命名的解耦。

  2、到底注册了哪些方法?

    在Object类中,除了有registerNatives这个本地方法之外,还有hashCode()、clone()等本地方法,而在Class类中有forName0()这样的本地方法等等。也就是说,凡是包含registerNatives()本地方法的类,同时也包含了其他本地方法。所以,显然,当包含registerNatives()方法的类被加载的时候,注册的方法就是该类所包含的除了registerNatives()方法以外的所有本地方法。

  3、为什么要注册?

      一个Java程序要想调用一个本地方法,需要执行两个步骤:

    (1)通过System.loadLibrary()将包含本地方法实现的动态文件加载进内存;

    (2)当Java程序需要调用本地方法时,虚拟机在加载的动态文件中定位并链接该本地方法,从而得以执行本地方法。

    registerNatives()方法的作用就是取代第二步,让程序主动将本地方法链接到调用方,当Java程序需要调用本地方法时就可以直接调用,而不需要虚拟机再去定位并链接。

  4、registerNatives() 本地方法的好处

  • 通过registerNatives方法在类被加载的时候就主动将本地方法链接到调用方,比当方法被使用时再由虚拟机来定位和链接更方便有效;
  • 如果本地方法在程序运行中更新了,可以通过调用registerNative方法进行更新;
  • Java程序需要调用一个本地应用提供的方法时,因为虚拟机只会检索本地动态库,因而虚拟机是无法定位到本地方法实现的,这个时候就只能使用registerNatives()方法进行主动链接。

以上是关于Java 之 native 关键字与 registerNatives 方法的主要内容,如果未能解决你的问题,请参考以下文章

Java源码之Object

[Js-Java SE]Java中的Native关键字与JNI

#yyds干货盘点#java高级用法之:在JNA中将本地方法映射到JAVA代码中

JVM 程序寄存器(Program Counter Register)

Java固有接口JNI(Java Native Interface)之HelloWorld

JAVA基础——Native关键字