Java中的原生关键字是什么?

What is the native keyword in Java for?

在玩这个谜题(它是一个Java关键词琐事游戏)时,我遇到了EDCOX1的0个关键字。

Java中的原生关键字是什么?


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

过去使用本地方法编写性能关键部分,但随着Java速度的提高,这一点不再常见。当

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

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

也见Java本地接口规范


最简单的例子让事情更清楚:

Main.java:

1
2
3
4
5
6
7
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));
    }
}

主要内容:

1
2
3
4
5
6
7
#include <jni.h>
#include"Main.h"

JNIEXPORT jint JNICALL Java_Main_square(
    JNIEnv *env, jobject obj, jint i) {
  return i * i;
}

编译并运行:

1
2
3
4
5
6
7
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

输出:

1
4

在Ubuntu 14.04 AMD64上测试。还与Oracle JDK 1.8.0_45合作。

Github上的示例,供您使用。

Java程序包/文件名中的下划线必须用C函数名中的_1来逃脱:在包含下划线的Android包名称中调用JNI函数

解释:

它允许您:

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

这可用于:

  • 使用更好的CPU汇编指令(非CPU可移植)在关键部分上更快地编写代码
  • 直接进行系统调用(不可移植操作系统)

以较低的可移植性为代价。

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

Android NDK

在本文中,这个概念完全相同,只是您必须使用android样板文件来设置它。

官方的NDK存储库包含"规范"示例,如Hello JNI应用程序:

  • http://Github.com/GooGeLAMAMPLE/Android NDK/BLUB/4DF5A705E78A0818C6B2DBC26B8E315D89D307/你好JNI/APP/SRC/MON/Java/COM/Simult/HeloLjNi/HeloLjNi Java JavaL39
  • https://github.com/googlesamples/android ndk/blob/4df5a2705e471a0818c6b2db26b8e315d89d307/hello jni/app/src/main/cpp/hello jni.c_l27

在android o上使用ndk的unzip.apk中,可以看到与lib/arm64-v8a/libnative-lib.so下的本机代码相对应的预编译.so

ToDO确认:此外,EDCOX1(5)表示它是一个共享库,我认为它是AOT预编译的.DEX对应于ART中的Java文件,也可以看到:Android中的ODEX文件是什么?那么,Java也可能是通过EDCOX1的6接口来运行的吗?

OpenJDK 8中的示例

让我们找到JDK8U60-B27中定义Object#clone的位置。

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

首先我们发现:

1
find . -name Object.java

它引导我们进入JDK/SRC/Stuty/Case/Java/Lang/Objava.JavaSyL212:

1
protected native Object clone() throws CloneNotSupportedException;

现在是最困难的部分,找到克隆人在所有间接过程中的位置。帮助我的问题是:

1
find . -iname object.c

它会找到C或C++文件,这些文件可能实现对象的本机方法。它将我们引入JDK/Stase/NET/Java/Lang/Objult.C.L.L47:

1
2
3
4
5
6
7
8
9
10
11
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符号:

1
grep -R JVM_Clone

这将我们引向hotspot/src/share/vm/prims/jvm.cpp_l580:

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

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


将EDCOX1的0个关键字应用于一个方法,以表明该方法是使用JNI(Java本机接口)在本机代码中实现的。


直接从Java语言规范:

A method that is native is implemented in platform-dependent code, typically written in another programming language such as C, C++, FORTRAN,or assembly language. The body of a native method is given as a semicolon only, indicating that the implementation is omitted, instead of a block.


斯莱克斯回答说,native关键字用于调用本机代码。

GWT还使用它来实现JavaScript方法。


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

The Java Native Interface (JNI) is a programming framework that enables Java code running in a Java Virtual Machine (JVM) to call, and to be called by, native applications (programs specific to a hardware and operating system platform) and libraries written in other languages such as C, C++ and assembly.

http://en.wikipedia.org/wiki/java_原生_界面


本机是非访问修饰符。它只能应用于方法。它表示方法或代码的依赖平台的实现。


  • EDCOX1×6是Java中的关键字,它指示平台依赖性。
  • EDCX1 6种方法是Java(JNI)与其他编程语言之间的接口。

本机是Java中的一个关键字,用于将未实现的结构(方法)抽象为抽象的,但它将是一个依赖于本地的代码,如本地代码和从本地堆栈执行而不是Java堆栈。