2012-11-14 6 views
1

J'ai une application Android qui se compose de quelques threads natifs (non attachés à JVM) qui doivent pouvoir appeler les méthodes d'un objet Java. La manière dont j'allais le faire consistait à créer une fonction JNI que j'appelle de l'objet Java pertinent, ce qui me permet d'obtenir et de mettre en cache les identifiants de méthode d'objet java, JNIEnv et les références d'objet dans un environnement natif statique. structure de données pour que mes threads natifs puissent (thread sécurisé) accéder aux méthodes requises (par exemple using (* env) -> CallVoidMethod (env, this, JavaMethodID, ...), etc;Multithreading natif et JNI

Je ne suis pas convaincu approche va fonctionner, puisque j'ai lu que le pointeur JNIEnv ne peut pas être partagé entre threads, et que seuls les threads qui sont attachés à la JVM peuvent faire ce genre de chose ...

Est-ce une approche viable?

+0

'JNIEnv' est valable uniquement pour le thread courant, mais' JavaVM' est mondiale . Donc, enregistrez un pointeur sur ce point, ainsi que des références globales à vos classes, objets, ID de méthode, et cela fonctionnera. –

+0

http://developer.android.com/training/articles/perf-jni.html – fadden

Répondre

2
  1. dans JNI_OnLoad, cache JavaVM*. C'est la seule chose persistante et valide à travers les threads.
  2. dès que vous avez configuré un thread natif, appelez le AttachCurrentThread et obtenez JNIEnv*, qui est valide uniquement pour ce thread unique.
  3. avec JavaVM* et JNIEnv*, recherchez vos jclass es, jobject s et jmethodID s. Ceux-ci sont toujours valables uniquement pour le thread unique auquel vous avez attaché.
  4. convertir jclass es et jobject s en références globales, de sorte qu'il persiste à travers les threads. jmethodID s n'ont pas besoin d'être globalisés, ce ne sont pas des jobs.
  5. Dans tous les autres threads natifs, vous devez à nouveau appeler AttachCurrentThread pour obtenir un JNIEnv* valide pour ce thread.
  6. Ne pas oublier de supprimer les références globales créées lorsque vous n'avez plus besoin (en JNI_OnUnload au plus tard)
+0

Merci Pavel, c'est exactement le genre de chose que je cherchais. Juste pour clarifier, une fois que j'ai caché les ID de méthode et globalisé mes références de classe et d'objet, tous les threads suivants peuvent utiliser les mêmes ID de méthode (par exemple dans CallVoidMethod()) à condition qu'ils le fassent par leur propre JNIEnv *. Je n'ai pas besoin d'un nouvel ensemble d'ID de méthode pour chaque thread, n'est-ce pas? –

+0

Oui, l'ID de méthode est valide n'importe où. La "globalisation" n'est nécessaire que pour les types de référence, c'est-à-dire tout ce qui dérive de jobject. jmethodID n'est pas un jobject, c'est un "[opaque structure] (http://docs.oracle.com/javase/1.3/docs/guide/jni/spec/types.doc.html#1064)". Ma théorie est que c'est juste une sorte d'index ordinal dans la table de fonctions de la classe (comme vtable pour C++) et est donc le même pour toutes les instances de la classe. –

+0

C'est génial, et merci encore. Je voterais votre réponse comme «utile», mais je n'ai pas encore assez de réputation. –