Вопрос-ответ

What is the native keyword in Java for?

Для чего используется ключевое слово native в Java?

Играя в эту головоломку (это викторина по ключевым словам Java), я наткнулся на native ключевое слово.

Для чего используется ключевое слово native в Java?

Переведено автоматически
Ответ 1

Минимальный исполняемый пример

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 должны экранироваться с помощью _1 в имени функции C, как указано в: Вызов функций JNI в имени пакета Android, содержащем подчеркивание

Интерпретация

native позволяет вам:


  • вызовите скомпилированную динамически загружаемую библиотеку (здесь написанную на C) с произвольным ассемблерным кодом из Java

  • и возвращаем результаты обратно в Java

Это может быть использовано для:


  • пишите более быстрый код в критической секции с лучшими инструкциями по сборке CPU (не переносимыми CPU)

  • выполнять прямые системные вызовы (не переносимые в ОС)

с компромиссом в пользу меньшей переносимости.

Вы также можете вызвать Java из C, но сначала вы должны создать JVM на C: Как вызывать функции Java из C ++?

Аналогичные API-интерфейсы native extension также присутствуют во многих других "языках виртуальных машин" по тем же причинам, например, Python, Node.js, Ruby.

Android NDK

Концепция в этом контексте точно такая же, за исключением того, что вы должны использовать Android boilerplate для ее настройки.

Официальный репозиторий NDK содержит "канонические" примеры, такие как приложение hello-jni:

В вашем unzip приложении .apk с NDK на Android O вы можете увидеть предварительно скомпилированный .so который соответствует машинному коду в разделе lib/arm64-v8a/libnative-lib.so.

Задача подтверждения: кроме того, file /data/app/com.android.appname-*/oat/arm64/base.odex говорится, что это разделяемая библиотека, которая, я думаю, является предварительно скомпилированным AOT .dex, соответствующим файлам Java в ART, смотрите также: Что такое файлы ODEX в Android? Так, может быть, Java на самом деле также запускается через native интерфейс?

Пример в OpenJDK 8

Давайте найдем, где Object#clone определено в jdk8u60-b27.

Мы придем к выводу, что оно реализовано с помощью native вызова.

Сначала мы находим:

find . -name Object.java

что приводит нас к jdk/src/share/classes/java /lang/Object.java#l212:

protected native Object clone() throws CloneNotSupportedException;

Теперь начинается сложная часть - найти, где находится clone, среди всех косвенных ссылок. Запрос, который мне помог, был:

find . -iname object.c

которое найдет файлы 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

Оно обозначает метод, который будет реализован на других языках, а не на Java. Он работает вместе с JNI (собственный интерфейс Java).

Собственные методы использовались в прошлом для написания разделов, критичных к производительности, но с ростом скорости Java это стало менее распространенным явлением. Собственные методы в настоящее время необходимы, когда


  • Вам нужно вызвать библиотеку из Java, написанную на другом языке.


  • Вам необходимо получить доступ к системным или аппаратным ресурсам, которые доступны только с другого языка (обычно C). На самом деле, многие системные функции, которые взаимодействуют с реальным компьютером (например, дисковый и сетевой ввод-вывод), могут делать это только потому, что они вызывают машинный код.


Смотрите также Спецификацию родного интерфейса Java

Ответ 3

Ключевое слово native применяется к методу, чтобы указать, что метод реализован в машинном коде с использованием JNI (Java Native Interface).

Ответ 4

Прямо из спецификации языка Java:


Метод, который native реализован в платформозависимом коде, обычно написанном на другом языке программирования, таком как C, C ++, FORTRAN или язык ассемблера. Тело native метода задается только в виде точки с запятой, указывающей, что реализация опущена, вместо блока.


2023-07-06 10:34 java