я использую jvm->GetEnv(&envThread, JNI_VERSION_1_6)
получить «env» для нескольких потоков, чтобы сделать несколько envThread->GetMethodID()
звонки. Оба потока правильно подключены к JVM.
Я вызываю функцию, возвращаемую «GetMethodID ()» в первом потоке без проблем, но когда второй поток пытается выполнить вызов, я вижу это сообщение:
art/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: thread Thread[13,tid=8207,Native,Thread*=0xaed08400,peer=0x12dcd080,"Thread-10224"]
using JNIEnv* from thread Thread[1,tid=8148,Runnable,Thread*=0xb4e07800,peer=0x87bc5ef0,"main"]
A/art(8148): art/runtime/check_jni.cc:65 in call to CallVoidMethodV
08-31 14:11:08.029: A/art(8148): art/runtime/check_jni.cc:65] "Thread-10224" prio=10 tid=13 Runnable
08-31 14:11:08.029: A/art(8148): art/runtime/check_jni.cc:65] group="main" sCount=0 dsCount=0 obj=0x12dcd080 self=0xaed08400
08-31 14:11:08.029: A/art(8148): art/runtime/check_jni.cc:65] sysTid=8207 nice=-11 cgrp=apps sched=0/0 handle=0xafb18b00
08-31 14:11:08.029: A/art(8148): art/runtime/check_jni.cc:65] state=R schedstat=( 17710887 6014947 64 ) utm=1 stm=0 core=3 HZ=100
08-31 14:11:08.029: A/art(8148): art/runtime/check_jni.cc:65] | stack=0xaee04000-0xaee06000 stackSize=1012KB
Потому что мой призыв к jvm->getEnv()
возвращается JNI_OK
для второго потока он уже прикреплен (как и ожидалось). Но что не ожидается, так это то, что возвращаемый JniENV точно такой же, как и в первом потоке. Таким образом вызывая аварию.
Кто-нибудь видел такие вещи раньше? Я совершенно потерян для того, что делать …
Благодарю.
Я думаю, что вы должны использовать AttachCurrentThread
из другого потока.
Вот аналогичный вопрос на ТАК:
void callback(int val) {
JNIEnv * g_env;
// double check it's all ok
int getEnvStat = g_vm->GetEnv((void **)&g_env, JNI_VERSION_1_6);
if (getEnvStat == JNI_EDETACHED) {
std::cout << "GetEnv: not attached" << std::endl;
if (g_vm->AttachCurrentThread((void **) &g_env, NULL) != 0) {
std::cout << "Failed to attach" << std::endl;
}
} else if (getEnvStat == JNI_OK) {
//
} else if (getEnvStat == JNI_EVERSION) {
std::cout << "GetEnv: version not supported" << std::endl;
}
g_env->CallVoidMethod(g_obj, g_mid, val);
if (g_env->ExceptionCheck()) {
g_env->ExceptionDescribe();
}
g_vm->DetachCurrentThread();
}
Вполне возможно, что код JNI в вашем проекте не написан для многозадачности и сохраняет содержимое Java в статических переменных. Я видел такой код. Как я понимаю, в одном проекте у ребят был какой-то унаследованный код C / C ++, который не передавал все эти параметры env, но в какой-то момент им нужно было вызывать Java. В другом проекте, как я понимаю, причиной использования глобальных переменных было решение руководства начать продажи, когда инженеры показали им прототип. Если вы видите имена переменных, как g_env
Это намек на то, что переменные когда-то были глобальными.
С другой стороны, я не видел ваш код, вероятно, эта заметка будет более актуальна для последующих прохожих, чем для вас.
Это было ошибкой в нашей кодовой базе, но это было не очень очевидно.