From 064b46779cb96225614ef3b5b1fa511b6acc3c9d Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Sun, 24 Sep 2023 04:58:19 +0200 Subject: [PATCH] JNI: Implement QJniObject::className to get the name of the class if not set If we construct the QJniObject from a jobject, then we know the jclass, but not the class's name. If className is called while the stored name is empty, get the name of the jclass and updated the stored value. Change-Id: Ic3332a6da2dac1eb6842f90da1b9264398a43155 Reviewed-by: Juha Vuolle --- src/corelib/kernel/qjniobject.cpp | 22 +++++++++++++++++-- .../kernel/qjniobject/tst_qjniobject.cpp | 17 ++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qjniobject.cpp b/src/corelib/kernel/qjniobject.cpp index e88e5b7ee6..069d0175ab 100644 --- a/src/corelib/kernel/qjniobject.cpp +++ b/src/corelib/kernel/qjniobject.cpp @@ -809,6 +809,21 @@ jclass QJniObject::objectClass() const */ QByteArray QJniObject::className() const { + if (d->m_className.isEmpty() && d->m_jclass && d->m_jobject) { + QJniEnvironment env; + if (env->PushLocalFrame(3) != JNI_OK) // JVM out of memory + return d->m_className; + jmethodID mid = env->GetMethodID(d->m_jclass, "getClass", "()Ljava/lang/Class;"); + jobject classObject = env->CallObjectMethod(d->m_jobject, mid); + jclass classObjectClass = env->GetObjectClass(classObject); + mid = env->GetMethodID(classObjectClass, "getName", "()Ljava/lang/String;"); + jstring stringObject = static_cast(env->CallObjectMethod(classObject, mid)); + const jsize length = env->GetStringUTFLength(stringObject); + const char* nameString = env->GetStringUTFChars(stringObject, NULL); + d->m_className = QByteArray::fromRawData(nameString, length).replace('.', '/'); + env->ReleaseStringUTFChars(stringObject, nameString); + env->PopLocalFrame(nullptr); + } return d->m_className; } @@ -1311,8 +1326,11 @@ QJniObject QJniObject::getObjectField(const char *fieldName, const char *signatu QJniObject QJniObject::fromString(const QString &string) { QJniEnvironment env; - return getCleanJniObject(env->NewString(reinterpret_cast(string.constData()), - string.length())); + jstring stringRef = env->NewString(reinterpret_cast(string.constData()), + string.length()); + QJniObject stringObject = getCleanJniObject(stringRef); + stringObject.d->m_className = "java/lang/String"; + return stringObject; } /*! diff --git a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp index 6f690f0091..36f6f5923e 100644 --- a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp +++ b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp @@ -42,6 +42,7 @@ private slots: void callObjectMethodTest(); void stringConvertionTest(); void compareOperatorTests(); + void className(); void callStaticObjectMethodClassName(); void callStaticObjectMethod(); void callStaticObjectMethodById(); @@ -300,6 +301,22 @@ void tst_QJniObject::compareOperatorTests() QVERIFY(!invalidStringObject.isValid()); } +void tst_QJniObject::className() +{ + const QString str("Hello!"); + QJniObject jString = QJniObject::fromString(str); + { + QCOMPARE(jString.className(), "java/lang/String"); + QCOMPARE(jString.toString(), str); + } + + { + QJniObject strObject = QJniObject("java/lang/String", jString.object()); + QCOMPARE(strObject.className(), "java/lang/String"); + QCOMPARE(strObject.toString(), str); + } +} + void tst_QJniObject::callStaticObjectMethodClassName() { QJniObject formatString = QJniObject::fromString(QLatin1String("test format"));