From 3a726628f13c8f46b447cf0844eb8a5b740a1993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Wed, 6 May 2015 18:15:03 +0200 Subject: Android: Store and use the class names as key when caching. Previously the jclass handle was part of the key used for caching the class' methods and fields. Using the jclass handle is not ideal, but it meant that we could easily create a key when the only identifier we had was the jobject or jclass handle. However, in Android 5.1, the re-use of handles seems to be more aggressive and therefore increasing the chance of a collision in the cache look-up. This change removes caching for all calls where we don't know the class name, as that is the only thing that guarantees that we create unique keys for each class. The consequence of this is that only calls that provide a class name will benefit from the internal caching. Task-number: QTBUG-45748 Change-Id: I0039d04e7c068debc9e3b3983632c45dc8e52309 Reviewed-by: Frank Meerkoetter Reviewed-by: Alex Blasche --- src/corelib/kernel/qjni.cpp | 472 +++++++++++++++++++++++++++----------------- src/corelib/kernel/qjni_p.h | 1 + 2 files changed, 293 insertions(+), 180 deletions(-) diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp index 8431ee3b67..344f7725a0 100644 --- a/src/corelib/kernel/qjni.cpp +++ b/src/corelib/kernel/qjni.cpp @@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE static inline QString keyBase() { - return QStringLiteral("%1%2%3"); + return QStringLiteral("%1%2:%3"); } static QString qt_convertJString(jstring string) @@ -72,15 +72,15 @@ typedef QHash JClassHash; Q_GLOBAL_STATIC(JClassHash, cachedClasses) Q_GLOBAL_STATIC(QReadWriteLock, cachedClassesLock) -static QString toDotEncodedClassName(const char *className) +static QByteArray toBinaryEncClassName(const QByteArray &className) { - return QString::fromLatin1(className).replace(QLatin1Char('/'), QLatin1Char('.')); + return QByteArray(className).replace('/', '.'); } -static jclass getCachedClass(const QString &classDotEnc, bool *isCached = 0) +static jclass getCachedClass(const QByteArray &classBinEnc, bool *isCached = 0) { QReadLocker locker(cachedClassesLock); - const QHash::const_iterator &it = cachedClasses->constFind(classDotEnc); + const QHash::const_iterator &it = cachedClasses->constFind(QString::fromLatin1(classBinEnc)); const bool found = (it != cachedClasses->constEnd()); if (isCached != 0) @@ -89,10 +89,12 @@ static jclass getCachedClass(const QString &classDotEnc, bool *isCached = 0) return found ? it.value() : 0; } -static jclass loadClassDotEnc(const QString &classDotEnc, JNIEnv *env) +inline static jclass loadClass(const QByteArray &className, JNIEnv *env, bool binEncoded = false) { + const QByteArray &binEncClassName = binEncoded ? className : toBinaryEncClassName(className); + bool isCached = false; - jclass clazz = getCachedClass(classDotEnc, &isCached); + jclass clazz = getCachedClass(binEncClassName, &isCached); if (clazz != 0 || isCached) return clazz; @@ -102,11 +104,12 @@ static jclass loadClassDotEnc(const QString &classDotEnc, JNIEnv *env) QWriteLocker locker(cachedClassesLock); // did we lose the race? - const QHash::const_iterator &it = cachedClasses->constFind(classDotEnc); + const QLatin1String key(binEncClassName); + const QHash::const_iterator &it = cachedClasses->constFind(key); if (it != cachedClasses->constEnd()) return it.value(); - QJNIObjectPrivate stringName = QJNIObjectPrivate::fromString(classDotEnc); + QJNIObjectPrivate stringName = QJNIObjectPrivate::fromString(key); QJNIObjectPrivate classObject = classLoader.callObjectMethod("loadClass", "(Ljava/lang/String;)Ljava/lang/Class;", stringName.object()); @@ -114,27 +117,40 @@ static jclass loadClassDotEnc(const QString &classDotEnc, JNIEnv *env) if (!exceptionCheckAndClear(env) && classObject.isValid()) clazz = static_cast(env->NewGlobalRef(classObject.object())); - cachedClasses->insert(classDotEnc, clazz); + cachedClasses->insert(key, clazz); return clazz; } -inline static jclass loadClass(const char *className, JNIEnv *env) -{ - return loadClassDotEnc(toDotEncodedClassName(className), env); -} - typedef QHash JMethodIDHash; Q_GLOBAL_STATIC(JMethodIDHash, cachedMethodID) Q_GLOBAL_STATIC(QReadWriteLock, cachedMethodIDLock) +static inline jmethodID getMethodID(JNIEnv *env, + jclass clazz, + const char *name, + const char *sig, + bool isStatic = false) +{ + jmethodID id = isStatic ? env->GetStaticMethodID(clazz, name, sig) + : env->GetMethodID(clazz, name, sig); + + if (exceptionCheckAndClear(env)) + return 0; + + return id; +} + static jmethodID getCachedMethodID(JNIEnv *env, jclass clazz, + const QByteArray &className, const char *name, const char *sig, bool isStatic = false) { - // TODO: We need to use something else then the ref. from clazz to avoid collisions. - const QString key = keyBase().arg(size_t(clazz)).arg(QLatin1String(name)).arg(QLatin1String(sig)); + if (className.isEmpty()) + return getMethodID(env, clazz, name, sig, isStatic); + + const QString key = keyBase().arg(QLatin1String(className)).arg(QLatin1String(name)).arg(QLatin1String(sig)); QHash::const_iterator it; { @@ -150,14 +166,7 @@ static jmethodID getCachedMethodID(JNIEnv *env, if (it != cachedMethodID->constEnd()) return it.value(); - jmethodID id = 0; - if (isStatic) - id = env->GetStaticMethodID(clazz, name, sig); - else - id = env->GetMethodID(clazz, name, sig); - - if (exceptionCheckAndClear(env)) - id = 0; + jmethodID id = getMethodID(env, clazz, name, sig, isStatic); cachedMethodID->insert(key, id); return id; @@ -168,13 +177,32 @@ typedef QHash JFieldIDHash; Q_GLOBAL_STATIC(JFieldIDHash, cachedFieldID) Q_GLOBAL_STATIC(QReadWriteLock, cachedFieldIDLock) +static inline jfieldID getFieldID(JNIEnv *env, + jclass clazz, + const char *name, + const char *sig, + bool isStatic = false) +{ + jfieldID id = isStatic ? env->GetStaticFieldID(clazz, name, sig) + : env->GetFieldID(clazz, name, sig); + + if (exceptionCheckAndClear(env)) + return 0; + + return id; +} + static jfieldID getCachedFieldID(JNIEnv *env, jclass clazz, + const QByteArray &className, const char *name, const char *sig, bool isStatic = false) { - const QString key = keyBase().arg(size_t(clazz)).arg(QLatin1String(name)).arg(QLatin1String(sig)); + if (className.isNull()) + return getFieldID(env, clazz, name, sig, isStatic); + + const QString key = keyBase().arg(QLatin1String(className)).arg(QLatin1String(name)).arg(QLatin1String(sig)); QHash::const_iterator it; { @@ -190,14 +218,7 @@ static jfieldID getCachedFieldID(JNIEnv *env, if (it != cachedFieldID->constEnd()) return it.value(); - jfieldID id = 0; - if (isStatic) - id = env->GetStaticFieldID(clazz, name, sig); - else - id = env->GetFieldID(clazz, name, sig); - - if (exceptionCheckAndClear(env)) - id = 0; + jfieldID id = getFieldID(env, clazz, name, sig, isStatic); cachedFieldID->insert(key, id); return id; @@ -241,7 +262,7 @@ JNIEnv *QJNIEnvironmentPrivate::operator->() jclass QJNIEnvironmentPrivate::findClass(const char *className, JNIEnv *env) { - const QString &classDotEnc = toDotEncodedClassName(className); + const QByteArray &classDotEnc = toBinaryEncClassName(className); bool isCached = false; jclass clazz = getCachedClass(classDotEnc, &isCached); @@ -250,9 +271,10 @@ jclass QJNIEnvironmentPrivate::findClass(const char *className, JNIEnv *env) if (found) return clazz; + const QLatin1String key(classDotEnc); if (env != 0) { // We got an env. pointer (We expect this to be the right env. and call FindClass()) QWriteLocker locker(cachedClassesLock); - const QHash::const_iterator &it = cachedClasses->constFind(classDotEnc); + const QHash::const_iterator &it = cachedClasses->constFind(key); // Did we lose the race? if (it != cachedClasses->constEnd()) return it.value(); @@ -264,11 +286,11 @@ jclass QJNIEnvironmentPrivate::findClass(const char *className, JNIEnv *env) } if (clazz != 0) - cachedClasses->insert(classDotEnc, clazz); + cachedClasses->insert(key, clazz); } if (clazz == 0) // We didn't get an env. pointer or we got one with the WRONG class loader... - clazz = loadClassDotEnc(classDotEnc, QJNIEnvironmentPrivate()); + clazz = loadClass(classDotEnc, QJNIEnvironmentPrivate(), true); return clazz; } @@ -309,11 +331,12 @@ QJNIObjectPrivate::QJNIObjectPrivate(const char *className) : d(new QJNIObjectData()) { QJNIEnvironmentPrivate env; - d->m_jclass = loadClass(className, env); + d->m_className = toBinaryEncClassName(className); + d->m_jclass = loadClass(d->m_className, env, true); d->m_own_jclass = false; if (d->m_jclass) { // get default constructor - jmethodID constructorId = getCachedMethodID(env, d->m_jclass, "", "()V"); + jmethodID constructorId = getCachedMethodID(env, d->m_jclass, d->m_className, "", "()V"); if (constructorId) { jobject obj = env->NewObject(d->m_jclass, constructorId); if (obj) { @@ -328,10 +351,11 @@ QJNIObjectPrivate::QJNIObjectPrivate(const char *className, const char *sig, ... : d(new QJNIObjectData()) { QJNIEnvironmentPrivate env; - d->m_jclass = loadClass(className, env); + d->m_className = toBinaryEncClassName(className); + d->m_jclass = loadClass(d->m_className, env, true); d->m_own_jclass = false; if (d->m_jclass) { - jmethodID constructorId = getCachedMethodID(env, d->m_jclass, "", sig); + jmethodID constructorId = getCachedMethodID(env, d->m_jclass, d->m_className, "", sig); if (constructorId) { va_list args; va_start(args, sig); @@ -349,10 +373,11 @@ QJNIObjectPrivate::QJNIObjectPrivate(const char *className, const char *sig, con : d(new QJNIObjectData()) { QJNIEnvironmentPrivate env; - d->m_jclass = loadClass(className, env); + d->m_className = toBinaryEncClassName(className); + d->m_jclass = loadClass(d->m_className, env, true); d->m_own_jclass = false; if (d->m_jclass) { - jmethodID constructorId = getCachedMethodID(env, d->m_jclass, "", sig); + jmethodID constructorId = getCachedMethodID(env, d->m_jclass, d->m_className, "", sig); if (constructorId) { jobject obj = env->NewObjectV(d->m_jclass, constructorId, args); if (obj) { @@ -370,7 +395,7 @@ QJNIObjectPrivate::QJNIObjectPrivate(jclass clazz) d->m_jclass = static_cast(env->NewGlobalRef(clazz)); if (d->m_jclass) { // get default constructor - jmethodID constructorId = getCachedMethodID(env, d->m_jclass, "", "()V"); + jmethodID constructorId = getMethodID(env, d->m_jclass, "", "()V"); if (constructorId) { jobject obj = env->NewObject(d->m_jclass, constructorId); if (obj) { @@ -388,7 +413,7 @@ QJNIObjectPrivate::QJNIObjectPrivate(jclass clazz, const char *sig, ...) if (clazz) { d->m_jclass = static_cast(env->NewGlobalRef(clazz)); if (d->m_jclass) { - jmethodID constructorId = getCachedMethodID(env, d->m_jclass, "", sig); + jmethodID constructorId = getMethodID(env, d->m_jclass, "", sig); if (constructorId) { va_list args; va_start(args, sig); @@ -410,7 +435,7 @@ QJNIObjectPrivate::QJNIObjectPrivate(jclass clazz, const char *sig, const QVaLis if (clazz) { d->m_jclass = static_cast(env->NewGlobalRef(clazz)); if (d->m_jclass) { - jmethodID constructorId = getCachedMethodID(env, d->m_jclass, "", sig); + jmethodID constructorId = getMethodID(env, d->m_jclass, "", sig); if (constructorId) { jobject obj = env->NewObjectV(d->m_jclass, constructorId, args); if (obj) { @@ -430,15 +455,15 @@ QJNIObjectPrivate::QJNIObjectPrivate(jobject obj) QJNIEnvironmentPrivate env; d->m_jobject = env->NewGlobalRef(obj); - jclass objectClass = env->GetObjectClass(d->m_jobject); - d->m_jclass = static_cast(env->NewGlobalRef(objectClass)); - env->DeleteLocalRef(objectClass); + jclass cls = env->GetObjectClass(obj); + d->m_jclass = static_cast(env->NewGlobalRef(cls)); + env->DeleteLocalRef(cls); } template <> void QJNIObjectPrivate::callMethodV(const char *methodName, const char *sig, va_list args) const { QJNIEnvironmentPrivate env; - jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig); + jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig); if (id) { env->CallVoidMethodV(d->m_jobject, id, args); } @@ -458,7 +483,7 @@ jboolean QJNIObjectPrivate::callMethodV(const char *methodName, const { QJNIEnvironmentPrivate env; jboolean res = 0; - jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig); + jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig); if (id) { res = env->CallBooleanMethodV(d->m_jobject, id, args); } @@ -480,7 +505,7 @@ jbyte QJNIObjectPrivate::callMethodV(const char *methodName, const char * { QJNIEnvironmentPrivate env; jbyte res = 0; - jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig); + jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig); if (id) { res = env->CallByteMethodV(d->m_jobject, id, args); } @@ -502,7 +527,7 @@ jchar QJNIObjectPrivate::callMethodV(const char *methodName, const char * { QJNIEnvironmentPrivate env; jchar res = 0; - jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig); + jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig); if (id) { res = env->CallCharMethodV(d->m_jobject, id, args); } @@ -524,7 +549,7 @@ jshort QJNIObjectPrivate::callMethodV(const char *methodName, const char { QJNIEnvironmentPrivate env; jshort res = 0; - jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig); + jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig); if (id) { res = env->CallShortMethodV(d->m_jobject, id, args); } @@ -546,7 +571,7 @@ jint QJNIObjectPrivate::callMethodV(const char *methodName, const char *si { QJNIEnvironmentPrivate env; jint res = 0; - jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig); + jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig); if (id) { res = env->CallIntMethodV(d->m_jobject, id, args); } @@ -568,7 +593,7 @@ jlong QJNIObjectPrivate::callMethodV(const char *methodName, const char * { QJNIEnvironmentPrivate env; jlong res = 0; - jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig); + jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig); if (id) { res = env->CallLongMethodV(d->m_jobject, id, args); } @@ -590,7 +615,7 @@ jfloat QJNIObjectPrivate::callMethodV(const char *methodName, const char { QJNIEnvironmentPrivate env; jfloat res = 0.f; - jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig); + jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig); if (id) { res = env->CallFloatMethodV(d->m_jobject, id, args); } @@ -612,7 +637,7 @@ jdouble QJNIObjectPrivate::callMethodV(const char *methodName, const ch { QJNIEnvironmentPrivate env; jdouble res = 0.; - jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig); + jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig); if (id) { res = env->CallDoubleMethodV(d->m_jobject, id, args); } @@ -692,7 +717,7 @@ void QJNIObjectPrivate::callStaticMethodV(const char *className, QJNIEnvironmentPrivate env; jclass clazz = loadClass(className, env); if (clazz) { - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true); if (id) { env->CallStaticVoidMethodV(clazz, id, args); } @@ -718,7 +743,7 @@ void QJNIObjectPrivate::callStaticMethodV(jclass clazz, va_list args) { QJNIEnvironmentPrivate env; - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getMethodID(env, clazz, methodName, sig, true); if (id) { env->CallStaticVoidMethodV(clazz, id, args); } @@ -746,7 +771,7 @@ jboolean QJNIObjectPrivate::callStaticMethodV(const char *className, jboolean res = 0; jclass clazz = loadClass(className, env); if (clazz) { - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true); if (id) { res = env->CallStaticBooleanMethodV(clazz, id, args); } @@ -776,7 +801,7 @@ jboolean QJNIObjectPrivate::callStaticMethodV(jclass clazz, { QJNIEnvironmentPrivate env; jboolean res = 0; - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getMethodID(env, clazz, methodName, sig, true); if (id) { res = env->CallStaticBooleanMethodV(clazz, id, args); } @@ -807,7 +832,7 @@ jbyte QJNIObjectPrivate::callStaticMethodV(const char *className, jbyte res = 0; jclass clazz = loadClass(className, env); if (clazz) { - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true); if (id) { res = env->CallStaticByteMethodV(clazz, id, args); } @@ -837,7 +862,7 @@ jbyte QJNIObjectPrivate::callStaticMethodV(jclass clazz, { QJNIEnvironmentPrivate env; jbyte res = 0; - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getMethodID(env, clazz, methodName, sig, true); if (id) { res = env->CallStaticByteMethodV(clazz, id, args); } @@ -868,7 +893,7 @@ jchar QJNIObjectPrivate::callStaticMethodV(const char *className, jchar res = 0; jclass clazz = loadClass(className, env); if (clazz) { - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true); if (id) { res = env->CallStaticCharMethodV(clazz, id, args); } @@ -898,7 +923,7 @@ jchar QJNIObjectPrivate::callStaticMethodV(jclass clazz, { QJNIEnvironmentPrivate env; jchar res = 0; - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getMethodID(env, clazz, methodName, sig, true); if (id) { res = env->CallStaticCharMethodV(clazz, id, args); } @@ -929,7 +954,7 @@ jshort QJNIObjectPrivate::callStaticMethodV(const char *className, jshort res = 0; jclass clazz = loadClass(className, env); if (clazz) { - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true); if (id) { res = env->CallStaticShortMethodV(clazz, id, args); } @@ -959,7 +984,7 @@ jshort QJNIObjectPrivate::callStaticMethodV(jclass clazz, { QJNIEnvironmentPrivate env; jshort res = 0; - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getMethodID(env, clazz, methodName, sig, true); if (id) { res = env->CallStaticShortMethodV(clazz, id, args); } @@ -990,7 +1015,7 @@ jint QJNIObjectPrivate::callStaticMethodV(const char *className, jint res = 0; jclass clazz = loadClass(className, env); if (clazz) { - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true); if (id) { res = env->CallStaticIntMethodV(clazz, id, args); } @@ -1020,7 +1045,7 @@ jint QJNIObjectPrivate::callStaticMethodV(jclass clazz, { QJNIEnvironmentPrivate env; jint res = 0; - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getMethodID(env, clazz, methodName, sig, true); if (id) { res = env->CallStaticIntMethodV(clazz, id, args); } @@ -1051,7 +1076,7 @@ jlong QJNIObjectPrivate::callStaticMethodV(const char *className, jlong res = 0; jclass clazz = loadClass(className, env); if (clazz) { - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true); if (id) { res = env->CallStaticLongMethodV(clazz, id, args); } @@ -1081,7 +1106,7 @@ jlong QJNIObjectPrivate::callStaticMethodV(jclass clazz, { QJNIEnvironmentPrivate env; jlong res = 0; - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getMethodID(env, clazz, methodName, sig, true); if (id) { res = env->CallStaticLongMethodV(clazz, id, args); } @@ -1112,7 +1137,7 @@ jfloat QJNIObjectPrivate::callStaticMethodV(const char *className, jfloat res = 0.f; jclass clazz = loadClass(className, env); if (clazz) { - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true); if (id) { res = env->CallStaticFloatMethodV(clazz, id, args); } @@ -1142,7 +1167,7 @@ jfloat QJNIObjectPrivate::callStaticMethodV(jclass clazz, { QJNIEnvironmentPrivate env; jfloat res = 0.f; - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getMethodID(env, clazz, methodName, sig, true); if (id) { res = env->CallStaticFloatMethodV(clazz, id, args); } @@ -1173,7 +1198,7 @@ jdouble QJNIObjectPrivate::callStaticMethodV(const char *className, jdouble res = 0.; jclass clazz = loadClass(className, env); if (clazz) { - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true); if (id) { res = env->CallStaticDoubleMethodV(clazz, id, args); } @@ -1203,7 +1228,7 @@ jdouble QJNIObjectPrivate::callStaticMethodV(jclass clazz, { QJNIEnvironmentPrivate env; jdouble res = 0.; - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getMethodID(env, clazz, methodName, sig, true); if (id) { res = env->CallStaticDoubleMethodV(clazz, id, args); } @@ -1338,7 +1363,7 @@ QJNIObjectPrivate QJNIObjectPrivate::callObjectMethodV(const char *methodName, { QJNIEnvironmentPrivate env; jobject res = 0; - jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig); + jmethodID id = getCachedMethodID(env, d->m_jclass, d->m_className, methodName, sig); if (id) { res = env->CallObjectMethodV(d->m_jobject, id, args); if (res && env->ExceptionCheck()) @@ -1418,7 +1443,7 @@ QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethodV(const char *classNa jobject res = 0; jclass clazz = loadClass(className, env); if (clazz) { - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getCachedMethodID(env, clazz, toBinaryEncClassName(className), methodName, sig, true); if (id) { res = env->CallStaticObjectMethodV(clazz, id, args); if (res && env->ExceptionCheck()) @@ -1450,7 +1475,7 @@ QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethodV(jclass clazz, { QJNIEnvironmentPrivate env; jobject res = 0; - jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); + jmethodID id = getMethodID(env, clazz, methodName, sig, true); if (id) { res = env->CallStaticObjectMethodV(clazz, id, args); if (res && env->ExceptionCheck()) @@ -1479,7 +1504,7 @@ jboolean QJNIObjectPrivate::getField(const char *fieldName) const { QJNIEnvironmentPrivate env; jboolean res = 0; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "Z"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "Z"); if (id) res = env->GetBooleanField(d->m_jobject, id); @@ -1491,7 +1516,7 @@ jbyte QJNIObjectPrivate::getField(const char *fieldName) const { QJNIEnvironmentPrivate env; jbyte res = 0; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "B"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "B"); if (id) res = env->GetByteField(d->m_jobject, id); @@ -1503,7 +1528,7 @@ jchar QJNIObjectPrivate::getField(const char *fieldName) const { QJNIEnvironmentPrivate env; jchar res = 0; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "C"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "C"); if (id) res = env->GetCharField(d->m_jobject, id); @@ -1515,7 +1540,7 @@ jshort QJNIObjectPrivate::getField(const char *fieldName) const { QJNIEnvironmentPrivate env; jshort res = 0; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "S"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "S"); if (id) res = env->GetShortField(d->m_jobject, id); @@ -1527,7 +1552,7 @@ jint QJNIObjectPrivate::getField(const char *fieldName) const { QJNIEnvironmentPrivate env; jint res = 0; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "I"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "I"); if (id) res = env->GetIntField(d->m_jobject, id); @@ -1539,7 +1564,7 @@ jlong QJNIObjectPrivate::getField(const char *fieldName) const { QJNIEnvironmentPrivate env; jlong res = 0; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "J"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "J"); if (id) res = env->GetLongField(d->m_jobject, id); @@ -1551,7 +1576,7 @@ jfloat QJNIObjectPrivate::getField(const char *fieldName) const { QJNIEnvironmentPrivate env; jfloat res = 0.f; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "F"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "F"); if (id) res = env->GetFloatField(d->m_jobject, id); @@ -1563,7 +1588,7 @@ jdouble QJNIObjectPrivate::getField(const char *fieldName) const { QJNIEnvironmentPrivate env; jdouble res = 0.; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "D"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "D"); if (id) res = env->GetDoubleField(d->m_jobject, id); @@ -1575,7 +1600,7 @@ jboolean QJNIObjectPrivate::getStaticField(jclass clazz, const char *f { QJNIEnvironmentPrivate env; jboolean res = 0; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "Z", true); + jfieldID id = getFieldID(env, clazz, fieldName, "Z", true); if (id) res = env->GetStaticBooleanField(clazz, id); @@ -1586,12 +1611,15 @@ template <> jboolean QJNIObjectPrivate::getStaticField(const char *className, const char *fieldName) { QJNIEnvironmentPrivate env; - jboolean res = 0; jclass clazz = loadClass(className, env); - if (clazz) - res = getStaticField(clazz, fieldName); + if (clazz == 0) + return 0; - return res; + jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "Z", true); + if (id == 0) + return 0; + + return env->GetStaticBooleanField(clazz, id); } template <> @@ -1599,7 +1627,7 @@ jbyte QJNIObjectPrivate::getStaticField(jclass clazz, const char *fieldNa { QJNIEnvironmentPrivate env; jbyte res = 0; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "B", true); + jfieldID id = getFieldID(env, clazz, fieldName, "B", true); if (id) res = env->GetStaticByteField(clazz, id); @@ -1610,12 +1638,15 @@ template <> jbyte QJNIObjectPrivate::getStaticField(const char *className, const char *fieldName) { QJNIEnvironmentPrivate env; - jbyte res = 0; jclass clazz = loadClass(className, env); - if (clazz) - res = getStaticField(clazz, fieldName); + if (clazz == 0) + return 0; - return res; + jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "B", true); + if (id == 0) + return 0; + + return env->GetStaticByteField(clazz, id); } template <> @@ -1623,7 +1654,7 @@ jchar QJNIObjectPrivate::getStaticField(jclass clazz, const char *fieldNa { QJNIEnvironmentPrivate env; jchar res = 0; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "C", true); + jfieldID id = getFieldID(env, clazz, fieldName, "C", true); if (id) res = env->GetStaticCharField(clazz, id); @@ -1634,12 +1665,15 @@ template <> jchar QJNIObjectPrivate::getStaticField(const char *className, const char *fieldName) { QJNIEnvironmentPrivate env; - jchar res = 0; jclass clazz = loadClass(className, env); - if (clazz) - res = getStaticField(clazz, fieldName); + if (clazz == 0) + return 0; - return res; + jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "C", true); + if (id == 0) + return 0; + + return env->GetStaticCharField(clazz, id); } template <> @@ -1647,7 +1681,7 @@ jshort QJNIObjectPrivate::getStaticField(jclass clazz, const char *field { QJNIEnvironmentPrivate env; jshort res = 0; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "S", true); + jfieldID id = getFieldID(env, clazz, fieldName, "S", true); if (id) res = env->GetStaticShortField(clazz, id); @@ -1658,12 +1692,15 @@ template <> jshort QJNIObjectPrivate::getStaticField(const char *className, const char *fieldName) { QJNIEnvironmentPrivate env; - jshort res = 0; jclass clazz = loadClass(className, env); - if (clazz) - res = getStaticField(clazz, fieldName); + if (clazz == 0) + return 0; - return res; + jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "S", true); + if (id == 0) + return 0; + + return env->GetStaticShortField(clazz, id); } template <> @@ -1671,7 +1708,7 @@ jint QJNIObjectPrivate::getStaticField(jclass clazz, const char *fieldName { QJNIEnvironmentPrivate env; jint res = 0; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "I", true); + jfieldID id = getFieldID(env, clazz, fieldName, "I", true); if (id) res = env->GetStaticIntField(clazz, id); @@ -1682,12 +1719,15 @@ template <> jint QJNIObjectPrivate::getStaticField(const char *className, const char *fieldName) { QJNIEnvironmentPrivate env; - jint res = 0; jclass clazz = loadClass(className, env); - if (clazz) - res = getStaticField(clazz, fieldName); + if (clazz == 0) + return 0; - return res; + jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "I", true); + if (id == 0) + return 0; + + return env->GetStaticIntField(clazz, id); } template <> @@ -1695,7 +1735,7 @@ jlong QJNIObjectPrivate::getStaticField(jclass clazz, const char *fieldNa { QJNIEnvironmentPrivate env; jlong res = 0; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "J", true); + jfieldID id = getFieldID(env, clazz, fieldName, "J", true); if (id) res = env->GetStaticLongField(clazz, id); @@ -1706,12 +1746,15 @@ template <> jlong QJNIObjectPrivate::getStaticField(const char *className, const char *fieldName) { QJNIEnvironmentPrivate env; - jlong res = 0; jclass clazz = loadClass(className, env); - if (clazz) - res = getStaticField(clazz, fieldName); + if (clazz == 0) + return 0; - return res; + jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "J", true); + if (id == 0) + return 0; + + return env->GetStaticLongField(clazz, id); } template <> @@ -1719,7 +1762,7 @@ jfloat QJNIObjectPrivate::getStaticField(jclass clazz, const char *field { QJNIEnvironmentPrivate env; jfloat res = 0.f; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "F", true); + jfieldID id = getFieldID(env, clazz, fieldName, "F", true); if (id) res = env->GetStaticFloatField(clazz, id); @@ -1730,12 +1773,15 @@ template <> jfloat QJNIObjectPrivate::getStaticField(const char *className, const char *fieldName) { QJNIEnvironmentPrivate env; - jfloat res = 0.f; jclass clazz = loadClass(className, env); - if (clazz) - res = getStaticField(clazz, fieldName); + if (clazz == 0) + return 0.f; - return res; + jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "F", true); + if (id == 0) + return 0.f; + + return env->GetStaticFloatField(clazz, id); } template <> @@ -1743,7 +1789,7 @@ jdouble QJNIObjectPrivate::getStaticField(jclass clazz, const char *fie { QJNIEnvironmentPrivate env; jdouble res = 0.; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "D", true); + jfieldID id = getFieldID(env, clazz, fieldName, "D", true); if (id) res = env->GetStaticDoubleField(clazz, id); @@ -1754,12 +1800,15 @@ template <> jdouble QJNIObjectPrivate::getStaticField(const char *className, const char *fieldName) { QJNIEnvironmentPrivate env; - jdouble res = 0.; jclass clazz = loadClass(className, env); - if (clazz) - res = getStaticField(clazz, fieldName); + if (clazz == 0) + return 0.; - return res; + jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, "D", true); + if (id == 0) + return 0.; + + return env->GetStaticDoubleField(clazz, id); } QJNIObjectPrivate QJNIObjectPrivate::getObjectField(const char *fieldName, @@ -1767,7 +1816,7 @@ QJNIObjectPrivate QJNIObjectPrivate::getObjectField(const char *fieldName, { QJNIEnvironmentPrivate env; jobject res = 0; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, sig); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, sig); if (id) { res = env->GetObjectField(d->m_jobject, id); if (res && env->ExceptionCheck()) @@ -1784,12 +1833,21 @@ QJNIObjectPrivate QJNIObjectPrivate::getStaticObjectField(const char *className, const char *sig) { QJNIEnvironmentPrivate env; - QJNIObjectPrivate res; jclass clazz = loadClass(className, env); - if (clazz) - res = getStaticObjectField(clazz, fieldName, sig); + if (clazz == 0) + return QJNIObjectPrivate(); - return res; + jfieldID id = getCachedFieldID(env, clazz, toBinaryEncClassName(className), fieldName, sig, true); + if (id == 0) + return QJNIObjectPrivate(); + + jobject res = env->GetStaticObjectField(clazz, id); + if (res && env->ExceptionCheck()) + res = 0; + + QJNIObjectPrivate obj(res); + env->DeleteLocalRef(res); + return obj; } QJNIObjectPrivate QJNIObjectPrivate::getStaticObjectField(jclass clazz, @@ -1798,7 +1856,7 @@ QJNIObjectPrivate QJNIObjectPrivate::getStaticObjectField(jclass clazz, { QJNIEnvironmentPrivate env; jobject res = 0; - jfieldID id = getCachedFieldID(env, clazz, fieldName, sig, true); + jfieldID id = getFieldID(env, clazz, fieldName, sig, true); if (id) { res = env->GetStaticObjectField(clazz, id); if (res && env->ExceptionCheck()) @@ -1814,7 +1872,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jboolean value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "Z"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "Z"); if (id) env->SetBooleanField(d->m_jobject, id, value); @@ -1824,7 +1882,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jbyte value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "B"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "B"); if (id) env->SetByteField(d->m_jobject, id, value); @@ -1834,7 +1892,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jchar value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "C"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "C"); if (id) env->SetCharField(d->m_jobject, id, value); @@ -1844,7 +1902,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jshort value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "S"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "S"); if (id) env->SetShortField(d->m_jobject, id, value); @@ -1854,7 +1912,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jint value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "I"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "I"); if (id) env->SetIntField(d->m_jobject, id, value); @@ -1864,7 +1922,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jlong value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "J"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "J"); if (id) env->SetLongField(d->m_jobject, id, value); @@ -1874,7 +1932,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jfloat value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "F"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "F"); if (id) env->SetFloatField(d->m_jobject, id, value); @@ -1884,7 +1942,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jdouble value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "D"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "D"); if (id) env->SetDoubleField(d->m_jobject, id, value); @@ -1894,7 +1952,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jbooleanArray value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[Z"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[Z"); if (id) env->SetObjectField(d->m_jobject, id, value); @@ -1904,7 +1962,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jbyteArray value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[B"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[B"); if (id) env->SetObjectField(d->m_jobject, id, value); @@ -1914,7 +1972,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jcharArray value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[C"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[C"); if (id) env->SetObjectField(d->m_jobject, id, value); @@ -1924,7 +1982,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jshortArray value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[S"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[S"); if (id) env->SetObjectField(d->m_jobject, id, value); @@ -1934,7 +1992,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jintArray value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[I"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[I"); if (id) env->SetObjectField(d->m_jobject, id, value); @@ -1944,7 +2002,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jlongArray value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[J"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[J"); if (id) env->SetObjectField(d->m_jobject, id, value); @@ -1954,7 +2012,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jfloatArray value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[F"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[F"); if (id) env->SetObjectField(d->m_jobject, id, value); @@ -1964,7 +2022,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jdoubleArray value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "[D"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "[D"); if (id) env->SetObjectField(d->m_jobject, id, value); @@ -1974,7 +2032,7 @@ template <> void QJNIObjectPrivate::setField(const char *fieldName, jstring value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, "Ljava/lang/String;"); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, "Ljava/lang/String;"); if (id) env->SetObjectField(d->m_jobject, id, value); @@ -1986,7 +2044,7 @@ void QJNIObjectPrivate::setField(const char *fieldName, jobject value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, sig); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, sig); if (id) env->SetObjectField(d->m_jobject, id, value); @@ -1998,7 +2056,7 @@ void QJNIObjectPrivate::setField(const char *fieldName, jobjectArray value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, d->m_jclass, fieldName, sig); + jfieldID id = getCachedFieldID(env, d->m_jclass, d->m_className, fieldName, sig); if (id) env->SetObjectField(d->m_jobject, id, value); @@ -2010,7 +2068,7 @@ void QJNIObjectPrivate::setStaticField(jclass clazz, jboolean value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "Z", true); + jfieldID id = getFieldID(env, clazz, fieldName, "Z", true); if (id) env->SetStaticBooleanField(clazz, id, value); } @@ -2022,8 +2080,14 @@ void QJNIObjectPrivate::setStaticField(const char *className, { QJNIEnvironmentPrivate env; jclass clazz = loadClass(className, env); - if (clazz) - setStaticField(clazz, fieldName, value); + if (clazz == 0) + return; + + jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "Z", true); + if (id == 0) + return; + + env->SetStaticBooleanField(clazz, id, value); } template <> @@ -2032,7 +2096,7 @@ void QJNIObjectPrivate::setStaticField(jclass clazz, jbyte value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "B", true); + jfieldID id = getFieldID(env, clazz, fieldName, "B", true); if (id) env->SetStaticByteField(clazz, id, value); } @@ -2044,8 +2108,14 @@ void QJNIObjectPrivate::setStaticField(const char *className, { QJNIEnvironmentPrivate env; jclass clazz = loadClass(className, env); - if (clazz) - setStaticField(clazz, fieldName, value); + if (clazz == 0) + return; + + jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "B", true); + if (id == 0) + return; + + env->SetStaticByteField(clazz, id, value); } template <> @@ -2054,7 +2124,7 @@ void QJNIObjectPrivate::setStaticField(jclass clazz, jchar value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "C", true); + jfieldID id = getFieldID(env, clazz, fieldName, "C", true); if (id) env->SetStaticCharField(clazz, id, value); } @@ -2066,8 +2136,14 @@ void QJNIObjectPrivate::setStaticField(const char *className, { QJNIEnvironmentPrivate env; jclass clazz = loadClass(className, env); - if (clazz) - setStaticField(clazz, fieldName, value); + if (clazz == 0) + return; + + jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "C", true); + if (id == 0) + return; + + env->SetStaticCharField(clazz, id, value); } template <> @@ -2076,7 +2152,7 @@ void QJNIObjectPrivate::setStaticField(jclass clazz, jshort value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "S", true); + jfieldID id = getFieldID(env, clazz, fieldName, "S", true); if (id) env->SetStaticShortField(clazz, id, value); } @@ -2088,8 +2164,14 @@ void QJNIObjectPrivate::setStaticField(const char *className, { QJNIEnvironmentPrivate env; jclass clazz = loadClass(className, env); - if (clazz) - setStaticField(clazz, fieldName, value); + if (clazz == 0) + return; + + jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "S", true); + if (id == 0) + return; + + env->SetStaticShortField(clazz, id, value); } template <> @@ -2098,7 +2180,7 @@ void QJNIObjectPrivate::setStaticField(jclass clazz, jint value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "I", true); + jfieldID id = getFieldID(env, clazz, fieldName, "I", true); if (id) env->SetStaticIntField(clazz, id, value); } @@ -2110,8 +2192,14 @@ void QJNIObjectPrivate::setStaticField(const char *className, { QJNIEnvironmentPrivate env; jclass clazz = loadClass(className, env); - if (clazz) - setStaticField(clazz, fieldName, value); + if (clazz == 0) + return; + + jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "I", true); + if (id == 0) + return; + + env->SetStaticIntField(clazz, id, value); } template <> @@ -2120,7 +2208,7 @@ void QJNIObjectPrivate::setStaticField(jclass clazz, jlong value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "J", true); + jfieldID id = getFieldID(env, clazz, fieldName, "J", true); if (id) env->SetStaticLongField(clazz, id, value); } @@ -2132,8 +2220,14 @@ void QJNIObjectPrivate::setStaticField(const char *className, { QJNIEnvironmentPrivate env; jclass clazz = loadClass(className, env); - if (clazz) - setStaticField(clazz, fieldName, value); + if (clazz == 0) + return; + + jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "J", true); + if (id == 0) + return; + + env->SetStaticLongField(clazz, id, value); } template <> @@ -2142,7 +2236,7 @@ void QJNIObjectPrivate::setStaticField(jclass clazz, jfloat value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "F", true); + jfieldID id = getFieldID(env, clazz, fieldName, "F", true); if (id) env->SetStaticFloatField(clazz, id, value); } @@ -2154,8 +2248,14 @@ void QJNIObjectPrivate::setStaticField(const char *className, { QJNIEnvironmentPrivate env; jclass clazz = loadClass(className, env); - if (clazz) - setStaticField(clazz, fieldName, value); + if (clazz == 0) + return; + + jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "F", true); + if (id == 0) + return; + + env->SetStaticFloatField(clazz, id, value); } template <> @@ -2164,7 +2264,7 @@ void QJNIObjectPrivate::setStaticField(jclass clazz, jdouble value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, clazz, fieldName, "D", true); + jfieldID id = getFieldID(env, clazz, fieldName, "D", true); if (id) env->SetStaticDoubleField(clazz, id, value); } @@ -2176,8 +2276,14 @@ void QJNIObjectPrivate::setStaticField(const char *className, { QJNIEnvironmentPrivate env; jclass clazz = loadClass(className, env); - if (clazz) - setStaticField(clazz, fieldName, value); + if (clazz == 0) + return; + + jfieldID id = getCachedFieldID(env, clazz, className, fieldName, "D", true); + if (id == 0) + return; + + env->SetStaticDoubleField(clazz, id, value); } template <> @@ -2187,7 +2293,7 @@ void QJNIObjectPrivate::setStaticField(jclass clazz, jobject value) { QJNIEnvironmentPrivate env; - jfieldID id = getCachedFieldID(env, clazz, fieldName, sig, true); + jfieldID id = getFieldID(env, clazz, fieldName, sig, true); if (id) env->SetStaticObjectField(clazz, id, value); } @@ -2200,8 +2306,14 @@ void QJNIObjectPrivate::setStaticField(const char *className, { QJNIEnvironmentPrivate env; jclass clazz = loadClass(className, env); - if (clazz) - setStaticField(clazz, fieldName, sig, value); + if (clazz == 0) + return; + + jfieldID id = getCachedFieldID(env, clazz, className, fieldName, sig, true); + if (id == 0) + return; + + env->SetStaticObjectField(clazz, id, value); } QJNIObjectPrivate QJNIObjectPrivate::fromString(const QString &string) diff --git a/src/corelib/kernel/qjni_p.h b/src/corelib/kernel/qjni_p.h index fb1982dc74..a62e9ee056 100644 --- a/src/corelib/kernel/qjni_p.h +++ b/src/corelib/kernel/qjni_p.h @@ -74,6 +74,7 @@ public: jobject m_jobject; jclass m_jclass; bool m_own_jclass; + QByteArray m_className; }; class Q_CORE_EXPORT QJNIObjectPrivate -- cgit v1.2.3 From 3eca75de67b3fd2c890715b30c7899cebc096fe9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 11 May 2015 18:30:00 +0900 Subject: Make qglobal.h complain if you use -fPIE Prior to Qt 5.4.2 (commit 36d6eb721e7d5997ade75e289d4088dc48678d0d), we allowed it, but now we need to enforce that it is not used. Note that -fPIE does define __PIC__, so we need this to catch the use of -fPIE. [ChangeLog][Important Behavior Changes] On x86 and x86-64 systems with ELF binaries (especially Linux), due to a new optimization in GCC 5.x in combination with a recent version of GNU binutils, compiling Qt applications with -fPIE is no longer enough. Applications now need to be compiled with the -fPIC option if Qt's option "reduce relocations" is active. Note that Clang is known to generate incompatible code even with -fPIC if the -flto option is active. Task-number: QTBUG-45755 Change-Id: I66a35ce5f88941f29aa6ffff13dd210e0aa2728f Reviewed-by: Dmitry Shachnev Reviewed-by: Simon Hausmann --- dist/changes-5.4.2 | 7 +++++++ src/corelib/global/qglobal.h | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/dist/changes-5.4.2 b/dist/changes-5.4.2 index e1ad9b6846..5827187e9e 100644 --- a/dist/changes-5.4.2 +++ b/dist/changes-5.4.2 @@ -34,6 +34,13 @@ information about a particular change. common EXIF-format (big-endian) was not working until 5.4.1. 5.4.2 restores the behavior of 5.4.0 and earlier for most EXIF-tagged JPEGs. EXIF orientation will be an opt-in starting with Qt 5.5. +- On x86 and x86-64 systems with ELF binaries (especially Linux), due to + a new optimization in GCC 5.x in combination with a recent version of + GNU binutils, compiling Qt applications with -fPIE is no longer + enough. Applications now need to be compiled with the -fPIC option if + Qt's option "reduce relocations" is active. Note that Clang is known + to generate incompatible code even with -fPIC if the -flto option is + active. **************************************************************************** * Library * diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index ef84662036..4547877da6 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -1047,9 +1047,9 @@ Q_CORE_EXPORT int qrand(); # define QT_NO_SHAREDMEMORY #endif -#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && !defined(__PIC__) +#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && (!defined(__PIC__) || defined(__PIE__)) # error "You must build your code with position independent code if Qt was built with -reduce-relocations. "\ - "Compile your code with -fPIC." + "Compile your code with -fPIC (-fPIE is not enough)." #endif namespace QtPrivate { -- cgit v1.2.3 From d14397b7298879e260bc7218a5f7539b6b94a2cf Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 12 May 2015 17:11:00 +0200 Subject: Windows: Fix exit crash of GUI applications when deleting argv[]. When passing Qt arguments followed by normal arguments, a double deletion may occur due to Qt shifting argv. For example: argv[] = app -qwindowgeometry +50+50 some_arg becomes: argv[] = app some_arg some_arg Terminate deletion when encountering the null pointer. Change-Id: I5279955b6bd463f5858d6e5e8e16a1f5d0945652 Reviewed-by: Joerg Bornemann --- src/winmain/qtmain_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/winmain/qtmain_win.cpp b/src/winmain/qtmain_win.cpp index 25b79543ba..459ca114a6 100644 --- a/src/winmain/qtmain_win.cpp +++ b/src/winmain/qtmain_win.cpp @@ -111,7 +111,7 @@ extern "C" int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR /*cmdParamarg*/, int argv[argc] = Q_NULLPTR; LocalFree(argvW); const int exitCode = main(argc, argv); - for (int i = 0; i < argc; ++i) + for (int i = 0; i < argc && argv[i]; ++i) delete [] argv[i]; delete [] argv; return exitCode; -- cgit v1.2.3 From 083c9269ed73e8771e1dbe10812696b45b7389f3 Mon Sep 17 00:00:00 2001 From: Evangelos Foutras Date: Mon, 11 May 2015 12:20:57 +0300 Subject: Try to ensure that -fPIC is used in CMake builds In commit 36d6eb721e7d5997ade75e289d4088dc48678d0d the -fPIE switch was replaced with -fPIC in an effort to avoid generating copy relocations which are incompatible with Qt5 when built with -reduce-relocations. Task-number: QTBUG-45755 Change-Id: I59a55ea15052f498104848c5fd867e563ddc2290 Reviewed-by: Thiago Macieira --- src/corelib/Qt5CoreConfigExtras.cmake.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in index 48d5f21447..d4abc5f271 100644 --- a/src/corelib/Qt5CoreConfigExtras.cmake.in +++ b/src/corelib/Qt5CoreConfigExtras.cmake.in @@ -70,8 +70,9 @@ set(_qt5_corelib_extra_includes) # Qt5_POSITION_INDEPENDENT_CODE variable is used in the # qt5_use_module # macro to add it. set(Qt5_POSITION_INDEPENDENT_CODE True) -set_property(TARGET Qt5::Core PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE \"ON\") set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"-fPIC\") +set_property(TARGET Qt5::Core PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE \"ON\") +set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_COMPILE_OPTIONS ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}) !!IF !isEmpty(QT_NAMESPACE) list(APPEND Qt5Core_DEFINITIONS -DQT_NAMESPACE=$$QT_NAMESPACE) -- cgit v1.2.3 From 189280026f091716dfda91ff652cc20b299683c2 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 13 May 2015 14:33:10 +0200 Subject: xcode generator: use absolute path when creating PBXFileReferences for libraries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the Xcode generator uses "sourceTree = " for all PBXFileReferences. But the paths we use for referencing libraries are relative. This patch will change this, so that we always use absolute paths to be consequent. This will fix a crash in Xcode that happens when opening projects generated by Qt. Change-Id: I3a372b93598a777c96ba353205cf19710a5923f5 Task-number: QTBUG-45966 Reviewed-by: Tor Arne Vestbø Reviewed-by: Oswald Buddenhagen --- qmake/generators/mac/pbuilder_pbx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 8f24c20712..b54f634cf9 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -950,7 +950,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) if(!path.isEmpty() && !libdirs.contains(path)) libdirs += path; } - library = fileFixify(library); + library = fileFixify(library, FileFixifyAbsolute); QString filetype = xcodeFiletypeForFilename(library); QString key = keyFor(library); if (!project->values("QMAKE_PBX_LIBRARIES").contains(key)) { -- cgit v1.2.3