FindClass à partir de n'importe quel thread dans Android JNI

Android JNI page conseils mentionne cette FAQ: Pourquoi ne pas FindClass à trouver ma classe?
Ils mentionnent plusieurs solutions et la dernière option est celle-ci:

Cache une référence pour le chargeur de classe de l'objet quelque part est pratique, et la question
loadClass appels directement. Cela nécessite un certain effort.

Donc, j'ai essayé de le faire fonctionner et il semble que peu importe, cette méthode ne fonctionne tout simplement pas pour moi. Finalement, j'ai compris comment utiliser le chargeur de classe, mais cela ne fonctionnera pas si à partir d'un thread natif j'essaie de loadClass qui n'a pas été touché/encore chargé. C'est essentiellement identique à l'env->FindClass de comportement lorsqu'il est appelé à partir d'un thread natif, à l'exception qu'il ne renvoie pas 0 pour les classes qui ont été déjà utilisés dans l'application. Aucune idée si je n'ai pas l'obtenir, ou il est impossible d'accéder aux classes à partir d'un thread natif qui n'étaient pas utilisés ou encore chargé.


EDIT: je vais vous donner plus d'informations pour expliquer exactement ce que je veux dire. Il est régulier de JNI env->FindClass(className), et un autre que j'ai écrit myFindClass(env, className) qui utilise la mise en cache ClassLoader->loadClass.

La classe que j'essaye d'accéder à de natif c/c++ est "com/noname/TestClient". À l'intérieur de myFindClass j'ai aussi utiliser env->FindClass et journal de la valeur qu'elle renvoie:

jclass myFindClass(JNIEnv * env, const char* name)
{
    ...
    jclass c0 = env->FindClass(name);
    jclass c1 = (jclass)env->CallObjectMethod(ClassLoader,
        MID_loadClass, envNewStringUTF(name));
    dlog("myFindClass(\"%s\") => c0:%p, c1:%p, c0 and c1 are same: %d",
        name, c0, c1, env->IsSameObject(c0, c1));
    ...
}

Ensuite, j'ai ces 3 combinaisons pour expliquer le problème.

1)

//inside JNI_OnLoad thread
myFindClass(env, "com/noname/TestClient");
...

//inside native thread created by pthread_create
myFindClass(env, "com/noname/TestClient");

- Je obtenir ce logcat:

myFindClass("com/noname/TestClent") => c0:0x41b64558, c1:0x41b64558,
c0 et c1 sont les mêmes: 1
...
myFindClass("com/noname/TestClent") => c0:0,
c1:0x41b64558, c0 et c1 sont les mêmes: 0

2)

//inside JNI_OnLoad thread
env->FindClass("com/noname/TestClient");
...

//inside native thread created by pthread_create
myFindClass("com/noname/TestClient");

- Je obtenir ce logcat:

myFindClass("com/noname/TestClent") => c0:0, c1:0x41b64558, c0 et c1 sont les mêmes: 0

3)

//inside JNI_OnLoad thread
//"com/noname/TestClient" isn't touched from JNI_OnLoad.
...

//inside native thread created by pthread_create
myFindClass(env, "com/noname/TestClient");

- Je obtenir ce logcat:

myFindClass("com/noname/TestClent") => c0:0, c1:0, c0 et c1 sont les mêmes: 1

En gros, mon problème est que le chargeur de classe ne trouve pas de ma classe dans le 3ème cas. Est-ce un bug? Ce qui peut être fait pour résoudre le problème?

EDIT2:
En plus de cela, il semble que le chargeur de classe::loadClass est clairement buggy. Si je demande myFindClass("noname/TestClent") ensuite, il retourne à certaines des ordures, et quand j'utilise ce qui est retourné jclass en aucune façon l'application se bloque.

  • Oui, c'est normal, les applications Android ne pas utiliser le système de chargeur de classe par défaut. Juste cache tout que vous avez besoin dans JNI_OnLoad() et qui prendra soin de cela.
  • Re: EDIT2: on dirait que la méthode a déclenché une exception, à quel point la valeur de retour n'est pas défini. loadClass() jamais renvoie null; elle renvoie soit la classe de référence ou elle lève une exception.
  • elle pourrait l'être. Je ne me souviens pas exactement quel était le problème, mais je l'ai résolu par la suite.
InformationsquelleAutor Pavel | 2012-11-07