FindClass from any thread in Android JNI FindClass from any thread in Android JNI android android

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;}


Try attaching your native thread to the JVM first.

The pointer to jvm you can obtain first thing in JNI_OnLoad

env->GetJavaVM(&jvm);

Then from your native thread

JNIEnv *env;jvm->AttachCurrentThread((void **)&env, NULL);

Then use that env for FindClass