Quels sont ces indigènes et comment ces méthodes fonctionnent-elles?
exemple minimal pour rendre les choses plus claires:
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;
}
Compilez et exécutez:
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
Sortie:
4
testé sur Ubuntu 14.04. A également travaillé avec Oracle JDK 1.8.0_45.
Example on GitHub pour que vous puissiez jouer avec.
interprétation:
Il vous permet de:
- appel a compilé bibliothèque chargée dynamiquement (ici écrit en C) avec le code d'assemblage arbitraire de Java
- et obtenir des résultats de retour en Java
Ceci peut être utilisé pour:
- écrire plus vite code sur une section critique avec de meilleures instructions d'assemblage CPU (pas de portables CPU)
- faire des appels système direct (non OS portable)
avec le compromis entre la Basse portabilité.
Il est également possible pour vous d'appeler Java à partir de C, mais vous devez d'abord créer une machine virtuelle Java en C: How to call Java functions from C++?
Exemple dans le OpenJDK 8
Trouvons trouver où Object#clone
est défini dans jdk8u60-b27.
D'abord, nous trouvons:
find . -name Object.java
qui nous conduit à jdk/src/share/classes/java/lang/Object.java#l212:
protected native Object clone() throws CloneNotSupportedException;
Maintenant vient la partie la plus difficile, trouver où clone est parmi tous les 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 de l'objet.Il nous conduit à 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]));
}
qui nous conduit au symbole JVM_Clone
:
grep -R JVM_Clone
qui nous conduit à 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 venons à la conclusion que c'est le point de définition.
Si hashcode() est implémenté par JVM uniquement, pourquoi faut-il qu'il soit * natif *? Que voulez-vous dire exactement par * intrinsèque * ici? – Geek