summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/kernel
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2023-10-19 15:18:48 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2023-10-23 15:10:28 +0200
commit72ad4191161a078a8c5828aa52ffe232e86117a8 (patch)
tree8db9c15a76735a87c8fa99c651c636f06ce8fb0c /tests/auto/corelib/kernel
parentfd48ce0b73c74dafd5db27bc1f2752ef665df7ef (diff)
JNI: Fix reference leak in QJniArray
When the array type is QJniObject or a subclass, then we need to explicitly release the local reference returned by GetObjectArrayElement in the QJniArray::at implementation. Do this by constructing the QJniObject via fromLocalRef, which does exactly that. Amends 80d4d55e250af1d643805bde3821987112cf09c1. Add a test case that stresses the local reference pool, and fix the old test case (which operates on a QJniArray<jobject>) to also release the local references. Change-Id: Ie293b1db9f1b6825376bbf12338b22dfc3f8c6e9 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Diffstat (limited to 'tests/auto/corelib/kernel')
-rw-r--r--tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp27
1 files changed, 24 insertions, 3 deletions
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<jobject[]>("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<jobject> newArray(QList<QJniObject>{QJniObject::fromString(u"one"_s),
+ QJniObject::fromString(u"two"_s),
+ QJniObject::fromString(u"three"_s)});
+ QVERIFY(newArray.isValid());
+ const QJniArray<QJniObject> reverse = TestClass::callStaticMethod<jobject[]>(
+ "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<TestClass> calledWithObject;
static int callbackWithObject(JNIEnv *, jobject, TestClass that)