diff --git a/src/corelib/kernel/qjniarray.h b/src/corelib/kernel/qjniarray.h index e5c9bc0e29..b6d4c4ab24 100644 --- a/src/corelib/kernel/qjniarray.h +++ b/src/corelib/kernel/qjniarray.h @@ -201,7 +201,11 @@ public: { JNIEnv *env = jniEnv(); if constexpr (std::is_convertible_v) { - return T{env->GetObjectArrayElement(object(), i)}; + jobject element = env->GetObjectArrayElement(object(), i); + if constexpr (std::is_base_of_v) + return QJniObject::fromLocalRef(element); + else + return T{element}; } else { T res = {}; if constexpr (std::is_same_v) diff --git a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp index c39a6d0343..c658c35bb0 100644 --- a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp +++ b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp @@ -113,6 +113,7 @@ private slots: void templateApiCheck(); void isClassAvailable(); void fromLocalRef(); + void largeObjectArray(); void callback_data(); void callback(); @@ -1534,9 +1535,10 @@ void tst_QJniObject::templateApiCheck() const auto reverse = testClass.callMethod("reverseObjectArray", newArray); QVERIFY(reverse.isValid()); QCOMPARE(reverse.size(), 3); - QCOMPARE(QJniObject(reverse.at(0)).toString(), u"three"_s); - QCOMPARE(QJniObject(reverse.at(1)).toString(), u"two"_s); - QCOMPARE(QJniObject(reverse.at(2)).toString(), u"one"_s); + // QJniArray::at returns a jobject that's a local reference; make sure we don't free it twice + QCOMPARE(QJniObject::fromLocalRef(reverse.at(0)).toString(), u"three"_s); + QCOMPARE(QJniObject::fromLocalRef(reverse.at(1)).toString(), u"two"_s); + QCOMPARE(QJniObject::fromLocalRef(reverse.at(2)).toString(), u"one"_s); } // jbooleanArray ------------------------------------------------------------------------------ @@ -1842,6 +1844,25 @@ void tst_QJniObject::fromLocalRef() QJniObject o = QJniObject::fromLocalRef(env->FindClass("java/lang/String")); } +void tst_QJniObject::largeObjectArray() +{ + QJniArray newArray(QList{QJniObject::fromString(u"one"_s), + QJniObject::fromString(u"two"_s), + QJniObject::fromString(u"three"_s)}); + QVERIFY(newArray.isValid()); + const QJniArray reverse = TestClass::callStaticMethod( + "staticReverseObjectArray", newArray); + QVERIFY(reverse.isValid()); + QCOMPARE(reverse.size(), 3); + + // make sure we don't leak local references + for (int i = 0; i < 10000; ++i) { + QVERIFY(reverse.at(0).isValid()); + QVERIFY(reverse.at(1).isValid()); + QVERIFY(reverse.at(2).isValid()); + } +} + static std::optional calledWithObject; static int callbackWithObject(JNIEnv *, jobject, TestClass that)