AndroidのJNIヒントページにこのFAQが記載されています:FindClassが私のクラスを見つけられなかったのはなぜですか? 彼らは複数の解決策に言及しており、最後の選択肢はこれです:
便利な場所にClassLoaderオブジェクトへの参照をキャッシュし、loadClass呼び出しを直接発行します。これには多少の努力が必要です。
それで、私はそれを機能させようとしました、そして、何があっても、この方法は単に私のために機能しないようです。最終的に、ClassLoaderの使用方法を理解しましたが、ネイティブスレッドから、まだタッチ/ロードされていないloadClassを実行しようとすると、機能しません。基本的に、ネイティブスレッドから呼び出されたときの動作はenv-> FindClassと同じですが、アプリですでに使用されているクラスに対して0が返されない点が異なります。私がそれを正しく理解しなかった場合、またはまだ使用/ロードされていないネイティブスレッドからクラスにアクセスすることが不可能であるかどうかはわかりません。
編集:私が正確に何を意味するのかを説明するために、より多くの情報を提供します。通常のJNIと、cachedを使用env->FindClass(className)
する私が書いた別のJNIがあります。myFindClass(env, className)
ClassLoader->loadClass
ネイティブc/c++からアクセスしようとしているクラスは「com/noname/TestClient」です。myFindClass内では、env->FindClassとそれが返すログ値も使用します。
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));
...
}
次に、問題を説明するためにこれらの3つの組み合わせがあります。
1)
//inside JNI_OnLoad thread
myFindClass(env, "com/noname/TestClient");
...
//inside native thread created by pthread_create
myFindClass(env, "com/noname/TestClient");
私はこのlogcatを取得します:
myFindClass( "com / noname / TestClent")=> c0:0x41b64558、c1:0x41b64558、c0とc1は同じです:1
...
myFindClass( "com / noname / TestClent")=> c0:0、c1:0x41b64558、 c0とc1は同じです:0
2)
//inside JNI_OnLoad thread
env->FindClass("com/noname/TestClient");
...
//inside native thread created by pthread_create
myFindClass("com/noname/TestClient");
私はこのlogcatを取得します:
myFindClass( "com / noname / TestClent")=> c0:0、c1:0x41b64558、c0とc1は同じです: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");
私はこのlogcatを取得します:
myFindClass( "com / noname / TestClent")=> c0:0、c1:0、c0、c1は同じです:1
基本的に、私の問題は、ClassLoaderが3番目のケースで私のクラスを見つけられないことです。バグですか?問題を解決するために何ができるでしょうか?
EDIT2: それに加えて、ClassLoader::loadClassは明らかにバグがあるようです。myFindClass( "noname / TestClent")に問い合わせると、ガベージが返され、返されたjclassを使用すると、アプリがクラッシュします。