Граючи в цю головоломку (Це дрібниці гри ключового слова Java), я натрапив наnative
ключове слово.
Для чого використовується нативне ключове слово на Java?
Граючи в цю головоломку (Це дрібниці гри ключового слова Java), я натрапив наnative
ключове слово.
Для чого використовується нативне ключове слово на Java?
Відповіді:
native
Ключове слово застосовується до методу , щоб вказати , що метод реалізований в нативному коді з допомогою JNI (Java Native Interface).
Приклад мінімальної експлуатації
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 з 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");
Розгорнувши купу макросів, ми приходимо до висновку, що це точка визначення.
static
native
методу Java другий параметр функції C ++ має тип, jclass
а не jobject
.
Він позначає метод, який буде реалізований іншими мовами, а не на Java. Він працює разом з JNI (Java Native Interface).
Рідні методи використовувалися в минулому для написання критичних розділів щодо продуктивності, але при швидшому збільшенні Java це зараз рідше. Народні методи в даний час потрібні, коли
Вам потрібно зателефонувати в бібліотеку з Java, яка написана іншою мовою.
Вам потрібно отримати доступ до системних або апаратних ресурсів, доступних лише з іншої мови (як правило, C). Насправді, багато системних функцій, які взаємодіють із реальним комп'ютером (наприклад, дисковий та мережевий IO), можуть це робити лише тому, що вони називають нативний код.
Див. Також Специфікація інтерфейсу Java Native
currentTimeMillis
є частиною JDK і до них зазначається, native
оскільки реалізація знаходиться у самому вихідному коді JDK. Дуже малоймовірно, що реалізація використовує мову складання; він, ймовірно, називає метод API операційної системи, над яким працює JVM. Наприклад, у Windows він може викликати метод DLL GetSystemTime
в kernel32.dll. В іншій ОС він матиме іншу реалізацію. Однак, коли ви використовуєте native
для написаного вами методу (на відміну від методу JDK), ви повинні забезпечити реалізацію за допомогою JNI.
currentTimeMillis
позначений як рідний, java.lang.System
тому він використовує JNI, чи не так?
Прямо з в специфікації мови Java :
Метод, який
native
реалізується в залежності від платформи коду, як правило, написаний іншою мовою програмування, такою як C, C ++, FORTRAN або мова складання. Тілоnative
методу задається лише крапкою з комою, що вказує, що реалізація замість блоку опущена.
функції, що реалізують нативний код, оголошуються нативними.
Java Native Interface (JNI) - це програма програмування, яка дозволяє коду Java, що працює у віртуальній машині Java (JVM), дзвонити та викликати його власними програмами (програмами, специфічними для апаратної та операційної системи платформи) та бібліотеками, записаними в інші мови, такі як C, C ++ та збірка.
native - це ключове слово в java, яке використовується для створення нереалізованої структури (методу) на зразок абстрактного, але це буде залежно від платформи, наприклад, кодового коду та виконання з рідного стека, а не java stack.
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
файлі:
availableProcessors
: позначено як рідний і не має атрибуту CodefreeMemory
: позначено як рідний і не має атрибуту CodetotalMemory
: позначено як рідний і не має атрибута CodemaxMemory
: позначено як рідний і не має атрибуту Codegc
: позначено як рідний і не має атрибуту 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
:
Довідково