From 965fc1148d5ae241972589fcbf772a0244656f14 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Tue, 1 Jun 2021 18:32:05 +0300 Subject: JNI: Add calls to get field IDs Task-number: QTBUG-92952 Change-Id: Ie68ede4b00a411064a29925b28b1f60a84d2d678 Reviewed-by: Ivan Solovev Reviewed-by: Ville Voutilainen --- src/corelib/kernel/qjnienvironment.cpp | 45 ++++++++++++++++++++ src/corelib/kernel/qjnienvironment.h | 2 + .../testdata/QtJniEnvironmentTestClass.java | 5 +++ .../kernel/qjnienvironment/tst_qjnienvironment.cpp | 48 ++++++++++++++++++++++ 4 files changed, 100 insertions(+) diff --git a/src/corelib/kernel/qjnienvironment.cpp b/src/corelib/kernel/qjnienvironment.cpp index 841fe747dc..4c21267b35 100644 --- a/src/corelib/kernel/qjnienvironment.cpp +++ b/src/corelib/kernel/qjnienvironment.cpp @@ -255,6 +255,51 @@ jmethodID QJniEnvironment::findStaticMethod(jclass clazz, const char *methodName return id; } + +/*! + Searches for an member field of a class \a clazz. The field is specified + by its \a fieldName and \a signature. + + Returns the field ID or \c nullptr if the field is not found. + + A usecase for this method is searching for class fields and caching their + IDs, so that they could later be used for getting/setting the fields. + + \since 6.2 +*/ +jfieldID QJniEnvironment::findField(jclass clazz, const char *fieldName, const char *signature) +{ + if (clazz) { + jfieldID id = d->jniEnv->GetFieldID(clazz, fieldName, signature); + if (!checkAndClearExceptions()) + return id; + } + + return nullptr; +} + +/*! + Searches for a static field of a class \a clazz. The field is specified + by its \a fieldName and \a signature. + + Returns the field ID or \c nullptr if the field is not found. + + A usecase for this method is searching for class fields and caching their + IDs, so that they could later be used for getting/setting the fields. + + \since 6.2 +*/ +jfieldID QJniEnvironment::findStaticField(jclass clazz, const char *fieldName, const char *signature) +{ + if (clazz) { + jfieldID id = d->jniEnv->GetStaticFieldID(clazz, fieldName, signature); + if (!checkAndClearExceptions()) + return id; + } + + return nullptr; +} + /*! \fn JavaVM *QJniEnvironment::javaVM() diff --git a/src/corelib/kernel/qjnienvironment.h b/src/corelib/kernel/qjnienvironment.h index 610dd054fe..df3753da83 100644 --- a/src/corelib/kernel/qjnienvironment.h +++ b/src/corelib/kernel/qjnienvironment.h @@ -61,6 +61,8 @@ public: jclass findClass(const char *className); jmethodID findMethod(jclass clazz, const char *methodName, const char *signature); jmethodID findStaticMethod(jclass clazz, const char *methodName, const char *signature); + jfieldID findField(jclass clazz, const char *fieldName, const char *signature); + jfieldID findStaticField(jclass clazz, const char *fieldName, const char *signature); static JavaVM *javaVM(); bool registerNativeMethods(const char *className, const JNINativeMethod methods[], int size); bool registerNativeMethods(jclass clazz, const JNINativeMethod methods[], int size); diff --git a/tests/auto/corelib/kernel/qjnienvironment/testdata/src/org/qtproject/qt/android/testdata/QtJniEnvironmentTestClass.java b/tests/auto/corelib/kernel/qjnienvironment/testdata/src/org/qtproject/qt/android/testdata/QtJniEnvironmentTestClass.java index 8f36dcc5fd..7bf6a7455a 100644 --- a/tests/auto/corelib/kernel/qjnienvironment/testdata/src/org/qtproject/qt/android/testdata/QtJniEnvironmentTestClass.java +++ b/tests/auto/corelib/kernel/qjnienvironment/testdata/src/org/qtproject/qt/android/testdata/QtJniEnvironmentTestClass.java @@ -33,6 +33,11 @@ public class QtJniEnvironmentTestClass private static native void callbackFromJava(String message); private static native void intCallbackFromJava(int value); + public final int INT_FIELD = 123; + public static final int S_INT_FIELD = 321; + + QtJniEnvironmentTestClass() {} + public static void appendJavaToString(String message) { callbackFromJava("From Java: " + message); diff --git a/tests/auto/corelib/kernel/qjnienvironment/tst_qjnienvironment.cpp b/tests/auto/corelib/kernel/qjnienvironment/tst_qjnienvironment.cpp index 06372ebad2..079de48948 100644 --- a/tests/auto/corelib/kernel/qjnienvironment/tst_qjnienvironment.cpp +++ b/tests/auto/corelib/kernel/qjnienvironment/tst_qjnienvironment.cpp @@ -49,6 +49,8 @@ private slots: void registerNativeMethodsByJclass(); void findMethod(); void findStaticMethod(); + void findField(); + void findStaticField(); }; void tst_QJniEnvironment::jniEnv() @@ -203,6 +205,52 @@ void tst_QJniEnvironment::findStaticMethod() QVERIFY(!env.checkAndClearExceptions()); } +void tst_QJniEnvironment::findField() +{ + QJniEnvironment env; + jclass clazz = env.findClass(javaTestClass); + QVERIFY(clazz != nullptr); + + // valid field + jfieldID validId = env.findField(clazz, "INT_FIELD", "I"); + QVERIFY(validId != nullptr); + + jmethodID constructorId = env.findMethod(clazz, "", "()V"); + QVERIFY(constructorId != nullptr); + jobject obj = env->NewObject(clazz, constructorId); + QVERIFY(!env.checkAndClearExceptions()); + int value = env->GetIntField(obj, validId); + QVERIFY(!env.checkAndClearExceptions()); + QVERIFY(value == 123); + + // invalid signature + jfieldID invalidId = env.findField(clazz, "unknown", "I"); + QVERIFY(invalidId == nullptr); + // check that all exceptions are already cleared + QVERIFY(!env.checkAndClearExceptions()); +} + +void tst_QJniEnvironment::findStaticField() +{ + QJniEnvironment env; + jclass clazz = env.findClass(javaTestClass); + QVERIFY(clazz != nullptr); + + // valid field + jfieldID validId = env.findStaticField(clazz, "S_INT_FIELD", "I"); + QVERIFY(validId != nullptr); + + int size = env->GetStaticIntField(clazz, validId); + QVERIFY(!env.checkAndClearExceptions()); + QVERIFY(size == 321); + + // invalid signature + jfieldID invalidId = env.findStaticField(clazz, "unknown", "I"); + QVERIFY(invalidId == nullptr); + // check that all exceptions are already cleared + QVERIFY(!env.checkAndClearExceptions()); +} + QTEST_MAIN(tst_QJniEnvironment) #include "tst_qjnienvironment.moc" -- cgit v1.2.3