Dans java, que fait la méthode statique privée registerNatives()
de la classe Object?
Les autres réponses sont techniquement correctes, mais pas très utiles pour une personne sans expérience JNI. 🙂
Normalement, pour que la JVM 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 s’appelle Java_java_lang_Object_registerNatives
. En utilisant registerNatives
(ou plutôt la fonction RegisterNatives
JNI), 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 nom “standard” de Java_java_lang_Object_getClass
.) Pour les fonctions répertoriées, les fonctions C associées sont répertoriées dans cette table, ce qui est plus pratique que l’écriture des fonctions de transfert.
L’enregistrement de fonctions natives est également utile si vous intégrez Java dans votre programme C et que vous souhaitez créer des liens avec des fonctions de l’application elle-même (par opposition à une bibliothèque partagée) ou que les fonctions utilisées ne sont pas “exscopes”. ne serait normalement pas trouvé par le mécanisme de recherche de méthode standard. L’enregistrement de fonctions natives peut également être utilisé pour “relier” une méthode native à une autre fonction C (utile si votre programme supporte par exemple des modules de chargement et de déchargement dynamics).
J’encourage tout le monde à lire le livre JNI , qui en parle et bien plus encore. 🙂
Ce qui peut être légèrement déroutant, c’est que le code affiché pour java.lang.Object.registerNatives
dans une réponse précédente est juste un exemple de la manière d’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 manières de rompre la boucle.
Suivez l’exemple de cette implémentation de la classe Object:
une. 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_
, qui contient un appel à la fonction JNI RegisterNatives
.
c. Assurez-vous que dans votre code Java, votre méthode Java registerNatives
est appelée avant tout appel à d’autres méthodes natives.
OU
Utilisez JNI_OnLoad
une. Dans votre bibliothèque native, définissez une fonction jint JNI_OnLoad(JavaVM *vm, void *reserved)
. Dans le corps de cette fonction, appelez la fonction JNI RegisterNatives
.
b. La machine virtuelle Java recherche et appelle JNI_OnLoad
lorsque votre bibliothèque native est chargée par System.loadLibrary
, que vous devriez déjà appeler, probablement dans un initialiseur statique pour votre classe. (Vous obtenez le pointeur env
requirejs en appelant la fonction GetEnv
dans la table vers laquelle pointe le pointeur vm
.)
Depuis que vous avez regardé le code source pour le trouver, c’est assez facile à deviner, non?
C’est une méthode native, appelée registerNatives, donc je suppose qu’elle enregistre les objects avec la plate-forme sous-jacente.
C’est aussi privé, donc il n’y a probablement rien à craindre.