Beim Spielen dieses Puzzles (es ist ein Java-Keyword-Quizspiel) bin ich auf das native
Keyword gestoßen.
Wofür wird das native Schlüsselwort in Java verwendet?
Beim Spielen dieses Puzzles (es ist ein Java-Keyword-Quizspiel) bin ich auf das native
Keyword gestoßen.
Wofür wird das native Schlüsselwort in Java verwendet?
Antworten:
Das native
Schlüsselwort wird auf eine Methode angewendet, um anzugeben, dass die Methode mithilfe von JNI (Java Native Interface) in nativem Code implementiert ist.
Minimal lauffähiges Beispiel
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));
}
}
Haupt c
#include <jni.h>
#include "Main.h"
JNIEXPORT jint JNICALL Java_Main_square(
JNIEnv *env, jobject obj, jint i) {
return i * i;
}
Kompilieren und ausführen:
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
Ausgabe:
4
Getestet unter Ubuntu 14.04 AMD64. Funktionierte auch mit Oracle JDK 1.8.0_45.
Beispiel auf GitHub, mit dem Sie spielen können.
Unterstriche in Java-Paket- / Dateinamen müssen _1
im C-Funktionsnamen maskiert werden, wie unter: Aufrufen von JNI-Funktionen im Android-Paketnamen mit Unterstrich
Deutung
native
erlaubt dir zu:
Dies könnte verwendet werden, um:
mit dem Kompromiss einer geringeren Portabilität.
Sie können Java auch von C aus aufrufen, müssen jedoch zuerst eine JVM in C erstellen: Wie rufe Java-Funktionen von C ++ auf?
Analoge native Erweiterungs-APIs sind aus den gleichen Gründen auch in vielen anderen "VM-Sprachen" vorhanden, z. B. Python , Node.js , Ruby .
Android NDK
Das Konzept ist in diesem Zusammenhang genau das gleiche, außer dass Sie Android Boilerplate verwenden müssen, um es einzurichten.
Das offizielle NDK-Repository enthält "kanonische" Beispiele wie die Hallo-JNI-App:
In unzip
einem .apk
mit NDK auf Android O können Sie den vorkompilierten .so
Code sehen, der dem nativen Code unter entspricht lib/arm64-v8a/libnative-lib.so
.
TODO bestätigen: Außerdem handelt file /data/app/com.android.appname-*/oat/arm64/base.odex
es sich um eine gemeinsam genutzte Bibliothek, bei der es sich meiner Meinung nach um die vorkompilierte AOT-.dex handelt, die den Java-Dateien in ART entspricht. Siehe auch: Was sind ODEX-Dateien in Android? Vielleicht wird Java tatsächlich auch über a ausgeführtnative
Schnittstelle ausgeführt?
Beispiel im OpenJDK 8
Lassen Sie uns finden, wo Object#clone
in jdk8u60-b27 definiert ist.
Wir werden daraus schließen, dass es mit a implementiert wird native
Aufruf umgesetzt wird.
Zuerst finden wir:
find . -name Object.java
was uns zu jdk / src / share / classes / java / lang / Object.java # l212 führt :
protected native Object clone() throws CloneNotSupportedException;
Jetzt kommt der schwierige Teil, herauszufinden, wo sich der Klon inmitten aller Indirektion befindet. Die Frage, die mir geholfen hat, war:
find . -iname object.c
Hier werden entweder C- oder C ++ - Dateien gefunden, die die nativen Methoden von Object implementieren könnten. Es führt uns zu 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]));
}
was uns zum JVM_Clone
Symbol führt:
grep -R JVM_Clone
was uns zu hotspot / src / share / vm / prims / jvm.cpp # l580 führt :
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
JVMWrapper("JVM_Clone");
Nachdem wir eine Reihe von Makros erweitert haben, kommen wir zu dem Schluss, dass dies der Definitionspunkt ist.
static
native
Java-Methode ist der zweite Parameter der C ++ - Funktion vom Typ jclass
und nicht vom Typ jobject
.
Es markiert eine Methode, die in anderen Sprachen implementiert wird, nicht in Java. Es funktioniert zusammen mit JNI (Java Native Interface).
In der Vergangenheit wurden native Methoden verwendet, um leistungskritische Abschnitte zu schreiben. Da Java jedoch immer schneller wird, ist dies jetzt weniger verbreitet. Native Methoden werden derzeit benötigt, wenn
Sie müssen eine Bibliothek aus Java aufrufen, die in einer anderen Sprache geschrieben ist.
Sie müssen auf System- oder Hardwareressourcen zugreifen, die nur von der anderen Sprache aus erreichbar sind (normalerweise C). Tatsächlich können viele Systemfunktionen, die mit einem realen Computer interagieren (z. B. Festplatten- und Netzwerk-E / A), dies nur, weil sie nativen Code aufrufen.
Siehe auch Java Native Interface-Spezifikation
currentTimeMillis
sind Teil des JDK und werden mit Anmerkungen versehen, native
da sich die Implementierung im JDK-Quellcode selbst befindet. Es ist sehr unwahrscheinlich, dass die Implementierung Assemblersprache verwendet. Es ruft wahrscheinlich eine API-Methode des Betriebssystems auf, auf dem die JVM ausgeführt wird. Unter Windows kann beispielsweise eine DLL-Methode GetSystemTime
in kernel32.dll aufgerufen werden . Auf einem anderen Betriebssystem wird es eine andere Implementierung haben. Wenn Sie jedoch native
für eine Methode verwenden, die Sie schreiben (im Gegensatz zu einer JDK-Methode), müssen Sie die Implementierung mithilfe von JNI bereitstellen.
currentTimeMillis
ist in als nativ markiert java.lang.System
, verwendet also JNI, stimmt das nicht?
Direkt aus der Java-Sprachspezifikation :
Eine Methode,
native
die in plattformabhängigem Code implementiert ist und normalerweise in einer anderen Programmiersprache wie C, C ++, FORTRAN oder Assemblersprache geschrieben ist. Der Hauptteil einernative
Methode wird nur als Semikolon angegeben, was darauf hinweist, dass die Implementierung anstelle eines Blocks weggelassen wird.
Funktionen, die nativen Code implementieren, werden als nativ deklariert.
Das Java Native Interface (JNI) ist ein Programmierframework, mit dem Java-Code, der in einer Java Virtual Machine (JVM) ausgeführt wird, native Anwendungen (Programme, die für eine Hardware- und Betriebssystemplattform spezifisch sind) und Bibliotheken, in die geschrieben wurde, aufrufen und von diesen aufgerufen werden kann andere Sprachen wie C, C ++ und Assembly.
native ist ein Schlüsselwort in Java, das verwendet wird, um nicht implementierte Strukturen (Methoden) wie abstrakt zu machen, aber es wäre plattformabhängig wie nativer Code und würde vom nativen Stapel ausgeführt, nicht vom Java-Stapel.
Die Java- native
Methode bietet einen Mechanismus für Java-Code zum Aufrufen von nativem OS-Code, entweder aus funktionalen oder aus Leistungsgründen.
Beispiel:
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 der entsprechenden Runtime.class
Datei in OpenJDK, die sich in befindet JAVA_HOME/jmods/java.base.jmod/classes/java/lang/Runtime.class
, sind diese Methoden enthalten und mit ACC_NATIVE
( 0x0100
) gekennzeichnet. Diese Methoden enthalten kein Code-Attribut . Dies bedeutet, dass diese Methode keine tatsächliche Codierungslogik in der Runtime.class
Datei enthält:
availableProcessors
: als nativ und ohne Code-Attribut markiertfreeMemory
: als nativ und ohne Code-Attribut markierttotalMemory
: als nativ und ohne Code-Attribut markiertmaxMemory
: als nativ und ohne Code-Attribut markiertgc
: als nativ und ohne Code-Attribut markiertDie eigentliche Codierungslogik befindet sich in der entsprechenden Runtime.c- Datei:
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 }
Diese C
Codierung wird in die Datei libjava.so
(Linux) oder libjava.dll
(Windows) kompiliert , die sich unter JAVA_HOME/jmods/java.base.jmod/lib/libjava.so
folgender Adresse befindet :
Referenz