查看原文:http://newfaction.net/2011/03/29/restrictions-on-calling-thread-jnienv.html
以下是JNI的一些限制:
There are certain constraints that you must keep in
mind when writing native methods that are to run in a multithreaded
environment. By understanding and programming within these
constraints, your native methods will execute safely no matter how
many threads simultaneously execute a given native method. For
example: * A JNIEnv pointer is only valid in the thread associated
with it. You must not pass this pointer from one thread to another,
or cache and use it in multiple threads. The Java virtual machine
passes a native method the same JNIEnv pointer in consecutive
invocations from the same thread, but passes different JNIEnv
pointers when invoking that native method from different threads.
Avoid the common mistake of caching the JNIEnv pointer of one
thread and using the pointer in another thread. * Local references
are valid only in the thread that created them. You must not pass
local references from one thread to another. You should always
convert local references to global references whenever there is a
possibility that multiple threads may use the same
reference.
针对如上的限制,JNIEnv 不能在多线程中共享相同的指针。而需要从JVM重新获取JNIEnv ,同时通过原JNIEnv
获取的Class 也是不能共享的,如下:
jclass clazz = env->FindClass("java/lang/String");
这里的clazz 就不能在多线程中共用,只能重新由新的JNIEnv 去FindClass 以下是线程中重新获取JNIEnv ,并用新的JNIEnv
调用FindClass 查找的例子:
static JavaVM* m_vm = 0;
void threadCallBack(DBusMessage *message)
{
int count = 0;
char buf[64];
static int index = 0;
JNIEnv *env;
if (m_vm->AttachCurrentThread(&env, NULL))
{
LOGE("callback_handler: failed to attach current thread\n");
return;
}
snprintf(buf, sizeof(buf), "signal index is %d", index);
jstring sigName = env->NewStringUTF(buf);
jclass objCls = env->FindClass("java/lang/Object");
jobjectArray objArray = env->NewObjectArray(index, objCls, 0);
for (; count < index ; count ++)
{
if (count == 0)
{
env->SetObjectArrayElement(objArray, count, 0);
}
else
{
snprintf(buf, sizeof(buf), "params ====>>> index is %d", index);
jstring params = env->NewStringUTF(buf);
env->SetObjectArrayElement(objArray, count, params);
}
}
env->CallVoidMethod(m_callBackObj, m_callBackMid, sigName, objArray);
index ++;
index > 5 ? 0 : index;
}
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jint result = -1;
LOGI("--------------JNI_OnLoad---------------------");
m_vm = vm;
}