Que fait la méthode registerNatives ()?
-
06-07-2019 - |
Question
En Java, que fait la méthode statique privée registerNatives()
de la classe Object?
La solution
Les autres réponses sont techniquement correctes, mais pas très utiles pour quelqu'un qui n'a pas d'expérience JNI. : -)
Normalement, pour que la machine virtuelle Java trouve vos fonctions natives, elles doivent être nommées d'une certaine manière. Par exemple, pour java.lang.Object.registerNatives
, la fonction C correspondante est nommée Java_java_lang_Object_registerNatives
. En utilisant registerNatives
(ou plutôt la fonction JNI RegisterNatives
), vous pouvez nommer vos fonctions C comme vous le souhaitez.
Voici le code C associé (à partir d'OpenJDK 6):
static JNINativeMethod methods[] = {
{"hashCode", "()I", (void *)&JVM_IHashCode},
{"wait", "(J)V", (void *)&JVM_MonitorWait},
{"notify", "()V", (void *)&JVM_MonitorNotify},
{"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll},
{"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]));
}
(Notez que Object.getClass
n'est pas dans la liste; il sera toujours appelé par le " standard " nom de Java_java_lang_Object_getClass
.) Pour les fonctions répertoriées, les fonctions C associées sont: comme indiqué dans ce tableau, ce qui est plus pratique que d’écrire de nombreuses fonctions de transfert.
L'enregistrement de fonctions natives est également utile si vous incorporez Java dans votre programme C et souhaitez créer un lien vers des fonctions dans l'application elle-même (par opposition à une bibliothèque partagée), ou si les fonctions utilisées ne sont pas autrement " exporté " ;, car ils ne seraient normalement pas trouvés par le mécanisme de recherche de méthode standard. L’enregistrement de fonctions natives peut également être utilisé pour & Quot; relier & Quot; une méthode native à une autre fonction C (utile si votre programme prend en charge le chargement et le déchargement dynamiques de modules, par exemple).
J'encourage tout le monde à lire le livre JNI , qui en parle et bien plus encore. : -)
Autres conseils
Ce qui peut être légèrement déroutant, c'est que le code indiqué pour java.lang.Object.registerNatives
dans une réponse précédente est simplement un exemple montrant comment enregistrer des fonctions natives. C'est le code qui (dans l'implémentation d'OpenJDK) enregistre les fonctions natives pour la classe Object. Pour enregistrer des fonctions natives pour votre propre classe, vous devez appeler la fonction JNI RegisterNatives
à partir du code natif de votre propre bibliothèque. Cela peut sembler un peu circulaire, mais il existe plusieurs façons de rompre la boucle.
-
Suivez l'exemple de cette implémentation de la classe Object:
a. Dans votre classe Java, déclarez une méthode native (de préférence statique) nommée
registerNatives
(ou tout autre nom. Peu importe).b. Dans votre code natif, définissez une fonction nommée
Java_<your fully qualified class name>_registerNatives
, qui contient un appel à la fonction JNIJNI_OnLoad
.c. Assurez-vous que dans votre code Java, votre méthode Java
jint JNI_OnLoad(JavaVM *vm, void *reserved)
est appelée avant tout appel à d'autres méthodes natives.
OU
-
Utiliser
System.loadLibrary
a. Dans votre bibliothèque native, définissez une fonction
env
. Dans le corps de cette fonction, appelez la fonction JNIGetEnv
.b. La machine virtuelle Java recherchera et appellera automatiquement
vm
lorsque votre bibliothèque native sera chargée par <=>, que vous devriez déjà appeler, probablement dans un initialiseur statique pour votre classe. (Vous obtenez le pointeur <=> requis en appelant la fonction <=> dans la table vers laquelle le pointeur <=> pointe.)