En jouant à ce puzzle (c'est un jeu-questionnaire sur les mots-clés Java), je suis tombé sur le native
mot - clé.
À quoi sert le mot-clé natif en Java?
En jouant à ce puzzle (c'est un jeu-questionnaire sur les mots-clés Java), je suis tombé sur le native
mot - clé.
À quoi sert le mot-clé natif en Java?
Réponses:
Le native
mot-clé est appliqué à une méthode pour indiquer que la méthode est implémentée en code natif à l'aide de JNI (Java Native Interface).
Exemple exécutable minimal
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));
}
}
Principal c
#include <jni.h>
#include "Main.h"
JNIEXPORT jint JNICALL Java_Main_square(
JNIEnv *env, jobject obj, jint i) {
return i * i;
}
Compiler et exécuter:
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
Production:
4
Testé sur Ubuntu 14.04 AMD64. Fonctionne également avec Oracle JDK 1.8.0_45.
Exemple sur GitHub pour jouer avec.
Les soulignements dans les noms de package / fichier Java doivent être échappés avec _1
le nom de la fonction C, comme indiqué dans: Appel des fonctions JNI dans le nom de package Android contenant un soulignement
Interprétation
native
vous permet de:
Cela pourrait être utilisé pour:
avec le compromis d'une portabilité inférieure.
Il vous est également possible d'appeler Java à partir de C, mais vous devez d'abord créer une JVM en C: Comment appeler des fonctions Java à partir de C ++?
Des API d'extension natives analogues sont également présentes dans de nombreux autres "langages VM" pour les mêmes raisons, par exemple Python , Node.js , Ruby .
Android NDK
Le concept est exactement le même dans ce contexte, sauf que vous devez utiliser un passe-partout Android pour le configurer.
Le référentiel NDK officiel contient des exemples "canoniques" tels que l'application hello-jni:
En vous unzip
une .apk
avec NDK sur Android O, vous pouvez voir la pré-compilé .so
correspondant au code natif sous lib/arm64-v8a/libnative-lib.so
.
TODO confirme: en outre, file /data/app/com.android.appname-*/oat/arm64/base.odex
dit qu'il s'agit d'une bibliothèque partagée, qui je pense est le .dex AOT précompilé correspondant aux fichiers Java dans ART, voir aussi: Que sont les fichiers ODEX dans Android? Alors peut-être que Java est également exécuté via une native
interface?
Exemple dans OpenJDK 8
Trouvons trouver où Object#clone
est défini dans jdk8u60-b27.
Nous conclurons qu'il est implémenté par un native
appel.
On trouve d'abord:
find . -name Object.java
ce qui nous amène à jdk / src / share / classes / java / lang / Object.java # l212 :
protected native Object clone() throws CloneNotSupportedException;
Vient maintenant la partie difficile, trouver où le clone est au milieu de toute l'indirection. La requête qui m'a aidé était:
find . -iname object.c
qui trouverait des fichiers C ou C ++ qui pourraient implémenter les méthodes natives d'Object. Cela nous amène à 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]));
}
ce qui nous amène au JVM_Clone
symbole:
grep -R JVM_Clone
ce qui nous amène à hotspot / src / share / vm / prims / jvm.cpp # l580 :
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
JVMWrapper("JVM_Clone");
Après avoir développé un tas de macros, nous arrivons à la conclusion que c'est le point de définition.
static
native
méthode Java, le deuxième paramètre de la fonction C ++ est de type jclass
et non jobject
.
Il marque une méthode, qu'il sera implémenté dans d'autres langages, pas en Java. Il fonctionne avec JNI (Java Native Interface).
Des méthodes natives ont été utilisées dans le passé pour écrire des sections critiques pour les performances, mais avec l'accélération de Java, cela est désormais moins courant. Des méthodes natives sont actuellement nécessaires lorsque
Vous devez appeler une bibliothèque à partir de Java écrite dans une autre langue.
Vous devez accéder aux ressources système ou matérielles qui sont uniquement accessibles à partir de l'autre langue (généralement C). En fait, de nombreuses fonctions système qui interagissent avec un ordinateur réel (disque et réseau IO, par exemple) ne peuvent le faire que parce qu'elles appellent du code natif.
Voir aussi Spécification de l'interface native Java
currentTimeMillis
font partie du JDK et sont annotées native
car l'implémentation se trouve dans le code source du JDK lui-même. Il est très peu probable que l'implémentation utilise le langage d'assemblage; il appelle probablement une méthode API du système d'exploitation sur lequel la JVM s'exécute. Par exemple, sous Windows, il peut appeler une méthode DLL GetSystemTime
dans kernel32.dll. Sur un autre OS, il aura une implémentation différente. Cependant, lorsque vous utilisez native
une méthode que vous écrivez (par opposition à une méthode JDK), vous devez fournir l'implémentation à l'aide de JNI.
currentTimeMillis
est marqué comme natif java.lang.System
donc il utilise JNI, n'est-ce pas?
Directement à partir de la spécification du langage Java :
Méthode
native
implémentée dans du code dépendant de la plate-forme, généralement écrit dans un autre langage de programmation tel que C, C ++, FORTRAN ou langage d'assemblage. Le corps d'unenative
méthode n'est donné que par un point-virgule, indiquant que l'implémentation est omise, au lieu d'un bloc.
les fonctions qui implémentent du code natif sont déclarées natives.
La Java Native Interface (JNI) est un cadre de programmation qui permet au code Java exécuté dans une machine virtuelle Java (JVM) d'appeler et d'être appelé par des applications natives (programmes spécifiques à une plate-forme matérielle et de système d'exploitation) et des bibliothèques écrites en d'autres langages tels que C, C ++ et l'assemblage.
native est un mot clé en java, qui est utilisé pour créer une structure (méthode) non implémentée comme abstraite, mais ce serait une plate-forme dépendante telle que le code natif et exécutée à partir de la pile native et non de la pile java.
La native
méthode Java fournit un mécanisme permettant au code Java d'appeler le code natif du système d'exploitation, pour des raisons fonctionnelles ou de performances.
Exemple:
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();
Dans le correspondant Runtime.class
fichier dans OpenJDK, situé dans JAVA_HOME/jmods/java.base.jmod/classes/java/lang/Runtime.class
, contient ces méthodes et les a marquées avec ACC_NATIVE
( 0x0100
), et ces méthodes ne contiennent pas l' attribut Code , ce qui signifie que ces méthodes n'ont pas de logique de codage réelle dans le Runtime.class
fichier:
availableProcessors
: balisé comme natif et sans attribut CodefreeMemory
: étiqueté comme natif et sans attribut CodetotalMemory
: étiqueté comme natif et sans attribut CodemaxMemory
: étiqueté comme natif et sans attribut Codegc
: étiqueté comme natif et sans attribut CodeEn fait, la logique de codage est dans le correspondant fichier 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 }
Et ces C
codages sont compilés dans le fichier libjava.so
(Linux) ou libjava.dll
(Windows), situé à JAVA_HOME/jmods/java.base.jmod/lib/libjava.so
:
Référence