Java JNIでMethodIdとJClassをキャッシュしようとしましたが、キャッシュされた値を使用するとEXE_BAD_ACCESSが発生しました。関数を使用してインラインで値を要求すると、エラーは消えてしまいました。私はグローバルな参照を使う必要があると分かりましたが、これはsegfaultを解決していません。JNIクラスID segfault
JNIキャッシング(わずかに時代遅れシグネチャ)に関連情報 - In JNI, how do I cache the class, methodID, and fieldIDs per IBM's performance recommendations?
ヘッダ:
extern jclass java_class_boolean;
extern jmethodID java_method_boolean;
CPP:
jclass java_class_boolean;
jmethodID java_method_boolean;
....
void initStatic(JNIEnv* env){
java_class_boolean = env->FindClass("java/lang/Boolean");
if (java_class_boolean){
env->NewGlobalRef(java_class_boolean);
java_method_boolean = env->GetMethodID(java_class_boolean, "<init>", "(Z)V");
}
}
使用(異なるCPPクラス、インポート共有ヘッダ):
jclass bc = env->FindClass("java/lang/Boolean");
jmethodID bm = env->GetMethodID(bc, "<init>", "(Z)V");
std::cout << "\nClass new: ";
std::cout << bc;
std::cout << " Class old: ";
std::cout << java_class_boolean;
std::cout << "\nMethod new: ";
std::cout << bm;
std::cout << " Method old: ";
std::cout << java_method_boolean;
std::cout << "\n";
result2 = env->NewObject(bc, bm, 1);
新しい
結果
クラス:古い0x7fcce4430110クラス:0x7fcce6a23098方法新しい:古い 0x7fcce471c288方法:0x7fcce471c288
しかし、キャッシュされたクラスを実行した場合、それがセグメンテーションフォルトを与えます。
V [libjvm.dylib + 0x309bcf] alloc_object(_jclass *、スレッド*)+ 0x15の
OSは、Mac 10.12です。 JDK 1.8.0_25。
これまでのテストではシングルスレッド化されており、JNI envも同じです。 ENVの
印刷記述:(JNIEnvの*)ENVのENV = 0x00007fcc3e0011e8 印刷記述:(JNIEnvの*)ENV = 0x00007fcc3e0011e8
両方initStatic及び将来の使用の "スレッド4" の上にあります同じenvインスタンス(JNIによって渡され、キャッシュされない)他のスレッドもありますが、segfaultとinitは同じスレッド上にあります。