web-dev-qa-db-fra.com

Que fait la méthode registerNatives ()?

En Java, que fait la méthode statique privée registerNatives() de la classe Object?

66
Hubris

Les autres réponses sont techniquement correctes, mais pas très utiles pour quelqu'un 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 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 bon vous semble.

Voici le code C associé (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]));
}

(Remarquerez 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 celles répertoriées dans ce tableau, ce qui est plus pratique que d'écrire un tas de fonctions de transfert.

L'enregistrement de fonctions natives est également utile si vous incorporez Java dans votre programme C et que vous souhaitez créer un lien vers des fonctions au sein de l'application elle-même (par opposition à une bibliothèque partagée), ou si les fonctions utilisées ne sont pas utilisées autrement, ils ne seront pas "exportés", car ceux-ci ne seraient normalement pas trouvés par le mécanisme de recherche de méthode standard. L'enregistrement des fonctions natives peut également être utilisé pour "relier" une méthode native à une autre fonction C (utile si votre programme prend en charge le chargement et le déchargement dynamiques des modules , par exemple).

J'encourage tout le monde à lire le livre JNI , qui en parle et bien plus encore. :-)

103
Chris Jester-Young

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 n'est qu'un exemple de la façon d'enregistrer des fonctions natives. Il s'agit du 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.

  1. Suivez l'exemple de cette implémentation de la classe Object:

    une. Dans votre classe Java classe, 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 JNI RegisterNatives.

    c. Assurez-vous que dans votre Java Java, votre méthode Java registerNatives) est appelée avant tout appel à d'autres méthodes natives.

OR

  1. 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. Le Java VM recherchera et appellera automatiquement JNI_OnLoad Lorsque votre bibliothèque native sera chargée par System.loadLibrary, Ce que vous devriez vous appelez déjà, probablement dans un initialiseur statique pour votre classe. (Vous obtenez le pointeur env requis en appelant la fonction GetEnv dans la table vers laquelle pointe le pointeur vm. )

8
Eric