Java中的native关键字有什么用?

发布于 2024-11-09 16:47:34 字数 155 浏览 2 评论 0原文

在玩这个谜题(这是一个 Java 关键字问答游戏)时,我遇到了 native 关键字。

Java中的native关键字有什么用?

While playing this puzzle (It's a Java keyword trivia game), I came across the native keyword.

What is the native keyword in Java used for?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

顾忌 2024-11-16 16:47:34

最小可运行示例

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 函数名称中使用 _1 进行转义,如下所述:在包含下划线的 Android 包名称中调用 JNI 函数

解释

native 允许您:

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

这可用于:

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

,但可移植性较低。

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

出于同样的原因,许多其他“VM 语言”中也存在类似的本机扩展 API,例如 Python, Node.js Node.jsRuby

Android NDK

在这种情况下,概念完全相同,只是您必须使用 Android 样板来设置它。

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

在 Android O 上使用 NDK 解压 .apk 时,您可以看到预编译的 .so 对应的内容lib/arm64-v8a/libnative-lib.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");

展开一堆宏后,我们得出的结论是,这就是定义点。

Minimal runnable example

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;
}

Compile and run:

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

Output:

4

Tested on Ubuntu 14.04 AMD64. Also worked with Oracle JDK 1.8.0_45.

Example on GitHub for you to play with.

Underscores in Java package / file names must be escaped with _1 in the C function name as mentioned at: Invoking JNI functions in Android package name containing underscore

Interpretation

native allows you to:

  • call a compiled dynamically loaded library (here written in C) with arbitrary assembly code from Java
  • and get results back into Java

This could be used to:

  • write faster code on a critical section with better CPU assembly instructions (not CPU portable)
  • make direct system calls (not OS portable)

with the tradeoff of lower portability.

It is also possible for you to call Java from C, but you must first create a JVM in C: How to call Java functions from C++?

Analogous native extension APIs are also present in many other "VM languages" for the same reasons, e.g. Python, Node.js, Ruby.

Android NDK

The concept is exact the same in this context, except that you have to use Android boilerplate to set it up.

The official NDK repository contains "canonical" examples such as the hello-jni app:

In you unzip an .apk with NDK on Android O, you can see the pre-compiled .so that corresponds to the native code under lib/arm64-v8a/libnative-lib.so.

TODO confirm: furthermore, file /data/app/com.android.appname-*/oat/arm64/base.odex, says it is a shared library, which I think is the AOT precompiled .dex corresponding to the Java files in ART, see also: What are ODEX files in Android? So maybe the Java is actually also run via a native interface?

Example in the OpenJDK 8

Let's find find where Object#clone is defined in jdk8u60-b27.

We will conclude that it is implemented with a native call.

First we find:

find . -name Object.java

which leads us to jdk/src/share/classes/java/lang/Object.java#l212:

protected native Object clone() throws CloneNotSupportedException;

Now comes the hard part, finding where clone is amidst all the indirection. The query that helped me was:

find . -iname object.c

which would find either C or C++ files that might implement Object's native methods. It leads us to 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]));
}

which leads us to the JVM_Clone symbol:

grep -R JVM_Clone

which leads us to hotspot/src/share/vm/prims/jvm.cpp#l580:

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

After expanding a bunch of macros, we come to the conclusion that this is the definition point.

山人契 2024-11-16 16:47:34

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

过去使用本机方法来编写性能关键部分,但随着 Java 变得越来越快,这种情况现在不太常见。 时,需要使用本机方法

  • 当前,当

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

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

参见
Java 本机接口规范

It marks a method, that it will be implemented in other languages, not in Java. It works together with JNI (Java Native Interface).

Native methods were used in the past to write performance critical sections but with Java getting faster this is now less common. Native methods are currently needed when

  • You need to call a library from Java that is written in other language.

  • You need to access system or hardware resources that are only reachable from the other language (typically C). Actually, many system functions that interact with real computer (disk and network IO, for instance) can only do this because they call native code.

See Also
Java Native Interface Specification

不气馁 2024-11-16 16:47:34

native 关键字应用于方法,表示该方法是使用 JNI(Java 本机接口)在本机代码中实现的。

The native keyword is applied to a method to indicate that the method is implemented in native code using JNI (Java Native Interface).

娇妻 2024-11-16 16:47:34

直接来自Java 语言规范

本机方法是用依赖于平台的代码实现的,通常用另一种编程语言(例如 C、C++、FORTRAN 或汇编语言)编写。 native 方法的主体仅以分号形式给出,表示省略实现,而不是块。

Straight from the Java Language Specification:

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.

白芷 2024-11-16 16:47:34

正如 SLaks 回答的那样,native 关键字用于调用本机代码。

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

As SLaks answered, the native keyword is for calling native code.

It also used by GWT for implementing javascript methods.

痴梦一场 2024-11-16 16:47:34

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

Java 本机接口 (JNI) 是一个编程框架,它使运行在 Java 虚拟机 (JVM) 中的 Java 代码能够调用本机应用程序(特定于硬件和操作系统平台的程序)以及被本机应用程序调用。用其他语言(例如 C、C++ 和汇编语言)编写的库。

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

functions that implement native code are declared native.

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_Native_Interface

北陌 2024-11-16 16:47:34

NATIVE 是非访问修饰符。它只能应用于 METHOD。
它指示方法或代码的平台相关实现。

NATIVE is Non access modifier.it can be applied only to METHOD.
It indicates the PLATFORM-DEPENDENT implementation of method or code.

樱娆 2024-11-16 16:47:34

Java native 方法为 Java 代码提供了一种出于功能或性能原因调用操作系统本机代码的机制。

示例:

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();

在OpenJDK中相应的Runtime.class文件中,位于JAVA_HOME/jmods/java.base.jmod/classes/java/lang/Runtime .class,包含这些方法并用 ACC_NATIVE (0x0100) 标记它们,并且这些方法不包含 Code 属性,这意味着这些方法没有任何实际编码Runtime.class 文件中的逻辑:

  • 方法 13 availableProcessors:标记为本机且无 Code 属性
  • 方法 14 freeMemory:标记为本机且无 Code方法
  • 15 totalMemory:标记为本机且无代码属性
  • 方法 16 maxMemory:标记为本机且无代码属性
  • 方法 17 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(Linux )或 libjava.dll (Windows) 文件,位于 JAVA_HOME/jmods/java.base.jmod/lib/libjava.so

在此处输入图像描述

< a href="https://i.sstatic.net/HjkZT.png" rel="noreferrer">在此处输入图像描述

参考

Java native method provides a mechanism for Java code to call OS native code, either due to functional or performance reasons.

Example:

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();

In the corresponding Runtime.class file in OpenJDK, located in JAVA_HOME/jmods/java.base.jmod/classes/java/lang/Runtime.class, contains these methods and tagged them with ACC_NATIVE (0x0100), and these methods do not contain the Code attribute, which means these method do not have any actual coding logic in the Runtime.class file:

  • Method 13 availableProcessors: tagged as native and no Code attribute
  • Method 14 freeMemory: tagged as native and no Code attribute
  • Method 15 totalMemory: tagged as native and no Code attribute
  • Method 16 maxMemory: tagged as native and no Code attribute
  • Method 17 gc: tagged as native and no Code attribute

enter image description here

The in fact coding logic is in the corresponding Runtime.c file:

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  }

And these C coding is compiled into the libjava.so (Linux) or libjava.dll (Windows) file, located at JAVA_HOME/jmods/java.base.jmod/lib/libjava.so:

enter image description here

enter image description here

Reference

遗心遗梦遗幸福 2024-11-16 16:47:34

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

native is a keyword in java , which is used to make unimplemented structure(method) like as abstract but it would be a platform dependent such as native code and execute from native stack not java stack.

耳根太软 2024-11-16 16:47:34
  • native是Java中的一个关键字,它表示平台相关。
  • native 方法充当 Java (JNI) 和其他编程语言之间的接口。
  • native is a keyword in Java, it indicates platform dependent.
  • native methods act as an interface between Java (JNI) and other programming languages.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文