Java中的native关键字是什么?

当玩这个难题 (这是一个Java关键字琐事游戏),我遇到了native关键字。

Java中使用的native关键字是什么?

native关键字应用于一个方法,以指示该方法是使用JNI(Java Native Interface)以本地代码实现的。

它标志着一种方法,它将以其他语言而不是Java来实现。 它与JNI(Java本地接口)一起工作。

过去使用本机方法来编写性能关键部分,但是Java变得更快,现在不那么常见了。 当时需要本地方法

  • 您需要从Java调用其他语言编写的库。

  • 您需要访问只能从其他语言(通常为C)访问的系统或硬件资源。 实际上,许多与真实计算机交互的系统函数(例如磁盘和网络IO)只能这样做,因为它们调用本机代码。

另请参阅Java本地接口规范

最小的例子 ,使事情更清晰:

Main.java

 public class Main { public native int square(int i); public static void main(String[] args) { System.loadLibrary("Main"); System.out.println(new Main().square(2)); } } 

Main.c

 #include <jni.h> #include "Main.h" JNIEXPORT jint JNICALL Java_Main_square( JNIEnv *env, jobject obj, jint i) { return i * i; } 

编译并运行

 sudo apt-get install build-essential openjdk-7-jdk export JAVA_HOME='/usr/lib/jvm/java-7-openjdk-amd64' javac Main.java javah -jni Main gcc -shared -fpic -o libMain.so -I${JAVA_HOME}/include \ -I${JAVA_HOME}/include/linux Main.c java -Djava.library.path=. Main 

输出

 4 

测试Ubuntu 14.04 AMD64。 还使用Oracle JDK 1.8.0_45。

在GitHub上的例子 ,你玩。

解读

它允许你:

  • 使用Java中的任意汇编代码调用一个编译的动态加载的库(这里用C编写)
  • 并将结果返回到Java

这可以用来:

  • 使用更好的CPU汇编指令在关键部分编写更快的代码(不是CPU便携式)
  • 直接进行系统调用(不是OS便携式)

与便携性较低的权衡。

您也可以从C中调用Java,但是您必须先在C中创建一个JVM: 如何从C ++调用Java函数?

Android NDK

在这种情况下,概念是完全一样的,除了你必须使用Android样板来设置它。

官方的NDK存储库包含“canonical”示例,如hello-jni应用程序:

在Android O中,使用NDK将.apk unzip ,您可以看到与lib/arm64-v8a/libnative-lib.so下的本地代码相对应的预编译的.so

TODO确认:此外, file /data/app/com.android.appname-*/oat/arm64/base.odex ,说这是一个共享库,我认为是AOT预编译.dex对应于ART文件中的Java文件另请参阅: Android中的ODEX文件是什么? 所以也许Java实际上也是通过native接口运行?

在OpenJDK 8中的例子

让我们找到在jdk8u60-b27中定义Object#clone位置。

我们将得出结论,它是用native调用来实现的。

首先我们发现:

 find . -name Object.java 

这导致我们到jdk / src / share / classes / java / lang / Object.java#l212 :

 protected native Object clone() throws CloneNotSupportedException; 

现在到了困难的部分,找到克隆在哪里间接所有的间接。 帮助我的查询是:

 find . -iname object.c 

它可以找到可能实现Object的本地方法的C或C ++文件。 它将我们引导到jdk / share / native / java / lang / Object.c#l47 :

 static JNINativeMethod methods[] = { ... {"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])); } 

这导致我们到JVM_Clone符号:

 grep -R JVM_Clone 

这导致我们到热点/ src / share / vm / prims / jvm.cpp#l580 :

 JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle)) JVMWrapper("JVM_Clone"); 

在扩展了一堆宏之后,我们得出这是定义的结论。

直接从Java语言规范

native方法是在平台相关的代码中实现的,通常用另一种编程语言如C,C ++,FORTRAN或汇编语言编写。 native方法的主体仅以分号给出,表示实现被省略,而不是块。

当SLaks回答时, native关键字用于调用本地代码。

它也被GWT用来实现javascript方法。

实现本地代码的函数被声明为本地的。

Java本地接口(Java Native Interface,JNI)是一种编程框架,它使得在Java虚拟机(JVM)中运行的Java代码可以调用本地应用程序(特定于硬件和操作系统平台的程序)和被调用的库其他语言如C,C ++和程序集。

http://en.wikipedia.org/wiki/Java_Native_Interface

native是java中的一个关键字,用来使得像抽象一样构造未实现的结构(方法),但是它将是一个依赖于平台的本地代码,并且从本地堆栈而不是Java堆栈执行。

NATIVE是非访问修饰符,它只能应用于METHOD。 它表明了PLATFORM-DEPENDENT方法或代码的实现。

  • native是java中的一个关键字,它表示平台依赖。
  • native方法作为Java( JNI )和其他编程语言之间的接口。

nativ e关键字用于声明一个方法,这个方法是在平台相关的代码(如C或C ++)中实现的。 当一个方法被标记为本地的,它不能有一个正文,而必须以分号结束。 Java本地接口(JNI)规范规定了实现本地方法的规则和准则,例如Java和本地应用程序之间的数据类型转换。

以下示例显示了一个声明为native的方法

 public class NativeExample { public native void fastCopyFile(String sourceFile, String destFile); } 

本地方法的缺点:

  • 本地方法与Windows中的.DLL(动态链接库)文件扩展名一起存储。 DLL文件是机器相关的。 因此,本地方法是不可移植的。

  • 由于本地方法使用机器码,所以会导致严重的安全问题。

native关键字用于声明一个在平台相关代码(如C或C ++)中实现的方法。 当一个方法被标记为本地的,它不能有一个正文,而必须以分号结束。 Java本地接口(JNI)规范规定了实现本地方法的规则和准则,例如Java和本地应用程序之间的数据类型转换。

以下示例显示了一个声明为native的方法的类:

 public class NativeExample { public native void fastCopyFile(String sourceFile, String destFile); }