Для чого є власне ключове слово у Java?


476

Граючи в цю головоломку (Це дрібниці гри ключового слова Java), я натрапив наnative ключове слово.

Для чого використовується нативне ключове слово на Java?


Відповіді:


343

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


3
Фактична реалізація не повинна використовувати JNI. Окремі методи JRE керуються внутрішньо JVM. Насправді, це навіть не обов'язково, щоб реалізація насправді рідний код. Це просто "реалізовано мовою, відмінною від мови програмування Java" .
Холгер

444

Приклад мінімальної експлуатації

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 дозволяє:

  • виклик складеної динамічно завантаженої бібліотеки (тут написано на С) з довільним складанням коду від Java
  • і повернути результати в Java

Це можна використати для:

  • пишіть швидший код у критичний розділ з кращими інструкціями щодо збирання процесора (не портативний процесор)
  • робити прямі системні дзвінки (не переносні ОС)

з компромісом нижчої портативності.

Можливо, ви також можете зателефонувати на Java з C, але спочатку потрібно створити JVM в C: Як викликати функції Java з C ++?

API аналогічних нативних розширень також є в багатьох інших "мовах VM" з тих же причин, наприклад, Python , Node.js , Ruby .

Android NDK

Концепція точно така ж і в цьому контексті, за винятком того, що для її налаштування вам потрібно використовувати котельну табличку Android.

Офіційний сховище NDK містить "канонічні" приклади, такі як додаток hello-jni:

У вас unzipв .apkс NDK на Android O, ви можете побачити прекомпіліруются , .soщо відповідає машинного коду підlib/arm64-v8a/libnative-lib.so .

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

Приклад у OpenJDK 8

Давайте знайдемо, де Object#cloneвизначено jdk8u60-b27.

Ми зробимо висновок, що він реалізований за допомогою nativeдзвінка.

Спочатку знаходимо:

find . -name Object.java

що призводить нас до jdk / src / share / класів / java / lang / Object.java # l212 :

protected native Object clone() throws CloneNotSupportedException;

Тепер ідеться про важку частину, яка знаходить, де знаходиться клон серед усієї непрямості. Запит, який мені допоміг:

find . -iname object.c

які могли б знайти файли C або C ++, які могли б реалізувати нативні методи Object. Це призводить нас до 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");

Розгорнувши купу макросів, ми приходимо до висновку, що це точка визначення.


1
Відмінна відповідь. Лише виноска: для static nativeметоду Java другий параметр функції C ++ має тип, jclassа не jobject.
SR_

@SR_ дякую за інформацію. Чи була помилка у моїй відповіді, чи це просто якась додаткова інформація?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

2
@Ciro - це додаткова інформація для тих, хто починає ваш приклад (відповідь з приблизно 300 на ТА може слугувати орієнтиром). У мене була функція з неправильним підписом, викликаним безладом на стеці, без помилок (під час будь-якого часу компіляції, посилання або запуску). Тому я вважаю важливим згадати, щоб бути уважним на цьому кроці.
SR_

419

Він позначає метод, який буде реалізований іншими мовами, а не на Java. Він працює разом з JNI (Java Native Interface).

Рідні методи використовувалися в минулому для написання критичних розділів щодо продуктивності, але при швидшому збільшенні Java це зараз рідше. Народні методи в даний час потрібні, коли

  • Вам потрібно зателефонувати в бібліотеку з Java, яка написана іншою мовою.

  • Вам потрібно отримати доступ до системних або апаратних ресурсів, доступних лише з іншої мови (як правило, C). Насправді, багато системних функцій, які взаємодіють із реальним комп'ютером (наприклад, дисковий та мережевий IO), можуть це робити лише тому, що вони називають нативний код.

Див. Також Специфікація інтерфейсу Java Native


3
Це моє розуміння, я пишу System.currentTimeMillis () (який є рідним) у файлі java, і тоді це спрацює, JNI зателефонує до бібліотек або деяких функцій, написаних на C або C ++ або мові збірки, а потім поверне деяке значення назад до мого коду Java . Наприклад: тут метод currentTimeMillis викликає нативний код за допомогою JNI, і цей кодовий код спілкується з системним ресурсом ex: таймером, що сидить на материнській платі і отримує тим самим повернене значення (системний час). виправте мене, будь ласка?
MKod

4
Методи @MKod, як-от, currentTimeMillisє частиною JDK і до них зазначається, nativeоскільки реалізація знаходиться у самому вихідному коді JDK. Дуже малоймовірно, що реалізація використовує мову складання; він, ймовірно, називає метод API операційної системи, над яким працює JVM. Наприклад, у Windows він може викликати метод DLL GetSystemTimeв kernel32.dll. В іншій ОС він матиме іншу реалізацію. Однак, коли ви використовуєте nativeдля написаного вами методу (на відміну від методу JDK), ви повинні забезпечити реалізацію за допомогою JNI.
Адам Берлі

Цей вислів є важливим для ключового слова Native ... "Вам потрібно отримати доступ до системних або апаратних ресурсів, доступних лише для іншої мови (як правило, C)".
atiqkhaled

@Kidburla Чи можу запитати, що ви маєте на увазі під "реалізацією у самому вихідному коді JDK"? currentTimeMillisпозначений як рідний, java.lang.Systemтому він використовує JNI, чи не так?
flow2k

1
@ flow2k так, те, що ви сказали, мабуть, правда, я не впевнений, чому я це сказав у своєму коментарі (більше 2 років тому)
Адам Берлі

59

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

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


19

Як відповів SLaks, то native ключове слово призначене для виклику нативного коду.

Він також використовується GWT для реалізації методів javascript.


13

функції, що реалізують нативний код, оголошуються нативними.

Java Native Interface (JNI) - це програма програмування, яка дозволяє коду Java, що працює у віртуальній машині Java (JVM), дзвонити та викликати його власними програмами (програмами, специфічними для апаратної та операційної системи платформи) та бібліотеками, записаними в інші мови, такі як C, C ++ та збірка.

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


8

NATIVE є модифікатором без доступу. Його можна застосувати лише до METHOD. Він вказує на реалізацію методу чи коду PLATFORM-DEPENDENT.


6

native - це ключове слово в java, яке використовується для створення нереалізованої структури (методу) на зразок абстрактного, але це буде залежно від платформи, наприклад, кодового коду та виконання з рідного стека, а не java stack.


6
  • native - ключове слово в java, воно вказує на залежність від платформи.
  • nativeметоди виступають як інтерфейс між Java ( JNI ) та іншими мовами програмування.

3

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

У відповідній Runtime.class файлі OpenJDK, розташованому в 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: позначено як рідний і не має атрибута Code
  • Метод 16 maxMemory: позначено як рідний і не має атрибуту Code
  • Спосіб 17 gc: позначено як рідний і не має атрибуту Code

введіть тут опис зображення

Фактично логіка кодування у відповідній файлі 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:

введіть тут опис зображення

введіть тут опис зображення

Довідково

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.