QJNI: Don't detach from the thread as long as the thread is alive.

Attaching and detaching the current thread to/from the VM on each jni call,
causes a new thread object to be created and triggers GC when detaching
(GC alone takes anything between 10-30 ms to finish on the test device).
Instead of detaching when the environment object goes out of scope, we
now detach when the thread exits.

Task-number: QTBUG-34279
Change-Id: Ia613934e61f914d4be63bfa1be8fdecf849928b0
Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
bb10
Christian Strømme 2013-10-24 16:24:48 +02:00 committed by The Qt Project
parent e1325cf26e
commit 746f7a5b28
1 changed files with 13 additions and 16 deletions

View File

@ -162,24 +162,31 @@ static jfieldID getCachedFieldID(JNIEnv *env,
return id;
}
Q_GLOBAL_STATIC(QThreadStorage<int>, refCount)
class QJNIEnvironmentPrivateTLS
{
public:
inline ~QJNIEnvironmentPrivateTLS()
{
QtAndroidPrivate::javaVM()->DetachCurrentThread();
}
};
Q_GLOBAL_STATIC(QThreadStorage<QJNIEnvironmentPrivateTLS *>, jniEnvTLS)
QJNIEnvironmentPrivate::QJNIEnvironmentPrivate()
: jniEnv(0)
{
JavaVM *vm = QtAndroidPrivate::javaVM();
if (vm->GetEnv((void**)&jniEnv, JNI_VERSION_1_6) == JNI_EDETACHED) {
if (vm->AttachCurrentThread(&jniEnv, 0) < 0)
if (vm->AttachCurrentThread(&jniEnv, 0) != JNI_OK)
return;
}
if (!jniEnv)
return;
if (!refCount->hasLocalData())
refCount->setLocalData(1);
else
refCount->setLocalData(refCount->localData() + 1);
if (!jniEnvTLS->hasLocalData())
jniEnvTLS->setLocalData(new QJNIEnvironmentPrivateTLS);
}
JNIEnv *QJNIEnvironmentPrivate::operator->()
@ -194,16 +201,6 @@ QJNIEnvironmentPrivate::operator JNIEnv* () const
QJNIEnvironmentPrivate::~QJNIEnvironmentPrivate()
{
if (!jniEnv)
return;
const int newRef = refCount->localData() - 1;
refCount->setLocalData(newRef);
if (newRef == 0)
QtAndroidPrivate::javaVM()->DetachCurrentThread();
jniEnv = 0;
}
QJNIObjectData::QJNIObjectData()