在玩this puzzle(这是一个Java关键字琐事游戏)时,我遇到了native
关键字。
Java中使用的native关键字是什么?
答案 0 :(得分:405)
它标记了一种方法,它将用其他语言实现,而不是用Java实现。它与JNI(Java Native Interface)一起使用。
过去使用本机方法来编写性能关键部分,但随着Java变得越来越快,现在不太常见了。
目前需要原生方法您需要从Java调用用其他语言编写的库。
您需要访问只能从其他语言(通常为C)访问的系统或硬件资源。实际上,许多与真实计算机(例如磁盘和网络IO)交互的系统功能只能这样做,因为它们调用本机代码。
答案 1 :(得分:403)
最小的例子让事情变得更加清晰:
<强> 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。
Java包/文件名中的下划线必须在C函数名称中使用_1
进行转义,如下所述:Invoking JNI functions in Android package name containing underscore
<强>解释强>:
它允许您:
这可以用于:
与较低的便携性进行权衡。
您也可以从C调用Java,但必须先在C中创建JVM:How to call Java functions from C++?
Android NDK
这个概念在这个上下文中是完全相同的,除了你必须使用Android样板来设置它。
官方NDK存储库包含“规范”示例,例如hello-jni app:
在Android O上使用NDK的unzip
和.apk
,您可以看到与.so
下的本机代码对应的预编译lib/arm64-v8a/libnative-lib.so
。
TODO确认:此外,file /data/app/com.android.appname-*/oat/arm64/base.odex
表示它是一个共享库,我认为是AOT预编译的.dex对应于ART中的Java文件,另请参阅:What are ODEX files in Android?所以也许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
引导我们hotspot/src/share/vm/prims/jvm.cpp#l580:
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
JVMWrapper("JVM_Clone");
在扩展了一堆宏之后,我们得出结论,这是定义点。
答案 2 :(得分:317)
native
关键字应用于方法,以指示使用JNI(Java Native Interface)在本机代码中实现该方法。
答案 3 :(得分:57)
直接来自the Java Language Specification:
native
方法是在依赖于平台的代码中实现的,通常用其他编程语言编写,例如C,C ++,FORTRAN或汇编语言。native
方法的主体仅以分号给出,表示省略了实现,而不是块。
答案 4 :(得分:19)
正如SLaks所回答,native
关键字用于调用本机代码。
它也被GWT用于实现javascript方法。
答案 5 :(得分:13)
实现本机代码的函数被声明为本机。
Java Native Interface(JNI)是一个编程框架,它使在Java虚拟机(JVM)中运行的Java代码能够调用本机应用程序(特定于硬件和操作系统平台的程序)并由其调用。用其他语言编写的库,如C,C ++和汇编。
答案 6 :(得分:8)
NATIVE是非访问修饰符。它只能应用于METHOD。 它表示方法或代码的PLATFORM-DEPENDENT实现。
答案 7 :(得分:6)
native是java中的一个关键字,用于制作未实现的结构(方法),如抽象,但它将依赖于平台,如本机代码,从本机堆栈执行而不是java堆栈。
答案 8 :(得分:3)
由于功能或性能原因,Java native
方法为Java代码提供了一种调用OS本机代码的机制。
示例:
606 public native int availableProcessors();
617 public native long freeMemory();
630 public native long totalMemory();
641 public native long maxMemory();
664 public native void gc();
在Runtime.class
中OpenJDK的相应JAVA_HOME/jmods/java.base.jmod/classes/java/lang/Runtime.class
文件中,包含这些方法并用ACC_NATIVE
(0x0100
)标记,并且这些方法不包含Code attribute,这意味着这些方法在Runtime.class
文件中没有任何实际的编码逻辑:
availableProcessors
:标记为本机且没有代码属性freeMemory
:标记为本机且没有代码属性totalMemory
:标记为本机且没有Code属性maxMemory
:标记为本机且没有Code属性gc
:标记为本机且没有代码属性实际上,编码逻辑在相应的Runtime.c文件中:
42 #include "java_lang_Runtime.h"
43
44 JNIEXPORT jlong JNICALL
45 Java_java_lang_Runtime_freeMemory(JNIEnv *env, jobject this)
46 {
47 return JVM_FreeMemory();
48 }
49
50 JNIEXPORT jlong JNICALL
51 Java_java_lang_Runtime_totalMemory(JNIEnv *env, jobject this)
52 {
53 return JVM_TotalMemory();
54 }
55
56 JNIEXPORT jlong JNICALL
57 Java_java_lang_Runtime_maxMemory(JNIEnv *env, jobject this)
58 {
59 return JVM_MaxMemory();
60 }
61
62 JNIEXPORT void JNICALL
63 Java_java_lang_Runtime_gc(JNIEnv *env, jobject this)
64 {
65 JVM_GC();
66 }
67
68 JNIEXPORT jint JNICALL
69 Java_java_lang_Runtime_availableProcessors(JNIEnv *env, jobject this)
70 {
71 return JVM_ActiveProcessorCount();
72 }
这些C
编码被编译到位于libjava.so
的{{1}}(Linux)或libjava.dll
(Windows)文件中:
参考