Ответ 1
Вы не можете кэшировать указатель JNIEnv
. Читайте об этом здесь:
Указатель интерфейса JNI (JNIEnv) действителен только в текущем потоке. Если другой поток должен получить доступ к виртуальной машине Java, он должен сначала вызвать AttachCurrentThread() для присоединения к виртуальной машине и получения указателя интерфейса JNI. После присоединения к виртуальной машине собственный поток работает так же, как обычный поток Java, запущенный внутри собственного метода. Нативный поток остается прикрепленным к виртуальной машине до тех пор, пока он не вызовет DetachCurrentThread(), чтобы отсоединить себя.
Что вы можете сделать, это кэшировать указатель JavaVM
.
static JavaVM *jvm;
[JNICALL etc] void init(JNIENv* env, [etc])
{
jint rs = (*env)->GetJavaVM(env, &jvm);
assert (rs == JNI_OK);
}
И тогда, когда вам понадобится указатель JNIEnv
из контекста, где он не указан, вы делаете это:
void someCallback() {
JNIEnv *env;
jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
assert (rs == JNI_OK);
// Use the env pointer...
}
Но всякий раз, когда вы вызываете собственный метод из Java, указывается указатель env для использования:
JNIEXPORT jint JNICALL Java_package_Class_method(JNIEnv *env, jobject obj) {
// just use the env pointer as is.
}