Findclass from Any Thread in Android Jni

FindClass from any thread in Android JNI

After much trying and crashing of my app, a colleague and I managed to cache and succesfully use the class loader in another, native, thread. The code we used is shown below (C++11, but easily converted to C++2003), posted here since we couldn't find any examples of the aforementioned "Cache a reference to the ClassLoader object somewhere handy, and issue loadClass calls directly. This requires some effort.". Calling findClass worked perfectly when called from a thread different from the one of JNI_OnLoad. I hope this helps.

JavaVM* gJvm = nullptr;
static jobject gClassLoader;
static jmethodID gFindClassMethod;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *pjvm, void *reserved) {
gJvm = pjvm; // cache the JavaVM pointer
auto env = getEnv();
//replace with one of your classes in the line below
auto randomClass = env->FindClass("com/example/RandomClass");
jclass classClass = env->GetObjectClass(randomClass);
auto classLoaderClass = env->FindClass("java/lang/ClassLoader");
auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader",
"()Ljava/lang/ClassLoader;");
gClassLoader = env->CallObjectMethod(randomClass, getClassLoaderMethod);
gFindClassMethod = env->GetMethodID(classLoaderClass, "findClass",
"(Ljava/lang/String;)Ljava/lang/Class;");

return JNI_VERSION_1_6;
}

jclass findClass(const char* name) {
return static_cast<jclass>(getEnv()->CallObjectMethod(gClassLoader, gFindClassMethod, getEnv()->NewStringUTF(name)));
}

JNIEnv* getEnv() {
JNIEnv *env;
int status = gJvm->GetEnv((void**)&env, JNI_VERSION_1_6);
if(status < 0) {
status = gJvm->AttachCurrentThread(&env, NULL);
if(status < 0) {
return nullptr;
}
}
return env;
}

Calling java method from different thread in ndk

The solution to my problem was to keep a reference to all the classes I will need in my different threads at the begginning of the ndk call before starting my threads and to use them inside those threads. I could also gave them to the thread as parameters.

Found it out thans to pskink and according to this documentation : https://developer.android.com/training/articles/perf-jni.html#faq_FindClass

JNI : Unable to find java class from native method in a callback

The answer and the official workaround can be found on developer.android. If you must go beyond pre-caching global references for all classes your native code might need, you will find a successful solution that caches the correct class loader here: FindClass from any thread in Android JNI

why JNIEnv can't find class com/google/android/gms/ads/identifier/AdvertisingIdClient?

Problem was solved.

The Application ClassLoader works well for my custom Class.

Because the App was not include com/google/android/gms/ads/identifier/AdvertisingIdClient. so we can not found it. Usually we get advertisingId through Intent to request Service.



Related Topics



Leave a reply



Submit