diff options
author | Christian Strømme <christian.stromme@digia.com> | 2014-09-29 14:16:28 +0200 |
---|---|---|
committer | Christian Stromme <christian.stromme@digia.com> | 2014-10-17 14:58:23 +0200 |
commit | 3d94a564f4c439ca0d1c2a0af807b9edeeb39299 (patch) | |
tree | 51730fe5e775c09e90bf3d8ed955f6c112d8d348 /src/corelib | |
parent | cf8f369f8575dcb9ca4d5116f3afc7cff4a080af (diff) |
Android: Improve cache logic in findClass()
This change adds guards to ensure that we only do a class
look-up once when calling QJNIEnvironmentPrivate::findClass().
IF someone calls findClass() with an environment that does not contain
a "valid" class loader, we should fallback to loadClass(),
but only once.
Change-Id: If5fc82956db889f3269bb33c98a16c49cae55def
Reviewed-by: Yoann Lopes <yoann.lopes@theqtcompany.com>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/kernel/qjni.cpp | 65 |
1 files changed, 35 insertions, 30 deletions
diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp index 173127b063..452e3464d6 100644 --- a/src/corelib/kernel/qjni.cpp +++ b/src/corelib/kernel/qjni.cpp @@ -80,38 +80,22 @@ static QString toDotEncodedClassName(const char *className) return QString::fromLatin1(className).replace(QLatin1Char('/'), QLatin1Char('.')); } -static jclass getCachedClass(const QString &classDotEnc) +static jclass getCachedClass(const QString &classDotEnc, bool *isCached = 0) { QHash<QString, jclass>::iterator it = cachedClasses->find(classDotEnc); + const bool found = (it != cachedClasses->end()); - if (it == cachedClasses->end()) - return 0; - - return it.value(); -} - -static jclass findClass(const char *className, JNIEnv *env) -{ - const QString &classDotEnc = toDotEncodedClassName(className); - jclass clazz = getCachedClass(classDotEnc); - if (clazz != 0) - return clazz; - - jclass fclazz = env->FindClass(className); - if (!exceptionCheckAndClear(env)) { - clazz = static_cast<jclass>(env->NewGlobalRef(fclazz)); - env->DeleteLocalRef(fclazz); - } + if (isCached != 0) + *isCached = found; - cachedClasses->insert(classDotEnc, clazz); - return clazz; + return found ? it.value() : 0; } -static jclass loadClass(const char *className, JNIEnv *env) +static jclass loadClassDotEnc(const QString &classDotEnc, JNIEnv *env) { - const QString &classDotEnc = toDotEncodedClassName(className); - jclass clazz = getCachedClass(classDotEnc); - if (clazz != 0) + bool isCached = false; + jclass clazz = getCachedClass(classDotEnc, &isCached); + if (clazz != 0 || isCached) return clazz; QJNIObjectPrivate classLoader = QtAndroidPrivate::classLoader(); @@ -130,6 +114,11 @@ static jclass loadClass(const char *className, JNIEnv *env) return clazz; } +inline static jclass loadClass(const char *className, JNIEnv *env) +{ + return loadClassDotEnc(toDotEncodedClassName(className), env); +} + typedef QHash<QString, jmethodID> JMethodIDHash; Q_GLOBAL_STATIC(JMethodIDHash, cachedMethodID) @@ -224,12 +213,28 @@ JNIEnv *QJNIEnvironmentPrivate::operator->() jclass QJNIEnvironmentPrivate::findClass(const char *className, JNIEnv *env) { - jclass clazz = 0; - if (env != 0) - clazz = ::findClass(className, env); + const QString &classDotEnc = toDotEncodedClassName(className); + bool isCached = false; + jclass clazz = getCachedClass(classDotEnc, &isCached); + + const bool found = (clazz != 0) || (clazz == 0 && isCached); + + if (found) + return clazz; + + if (env != 0) { // We got an env. pointer (We expect this to be the right env. and call FindClass()) + jclass fclazz = env->FindClass(className); + if (!exceptionCheckAndClear(env)) { + clazz = static_cast<jclass>(env->NewGlobalRef(fclazz)); + env->DeleteLocalRef(fclazz); + } + + if (clazz != 0) + cachedClasses->insert(classDotEnc, clazz); + } - if (clazz == 0) - clazz = loadClass(className, QJNIEnvironmentPrivate()); + if (clazz == 0) // We didn't get an env. pointer or we got one with the WRONG class loader... + clazz = loadClassDotEnc(classDotEnc, QJNIEnvironmentPrivate()); return clazz; } |