Use JNI FindClass on Android properly

53

Improper usage of JNIEnv::FindClass function will return NULL or even crash the application. Things you should know about how FindClass does work:

You should pass into FindClass a fully-qualified class name and replace dots with slashes, for example: android/net/Uri instead of android.net.Uri.

You should call FindClass from the main Java thread only. This is the thread where you do event polling with ALooper_pollAll function.

That's enough if you're using FindClass to find built-in classes. However that won't work in case you need to find a class from your own package — using it directly you'll still get NULL.

To find a class from your own package you'll have to use a class loader. So, if you need to find com.package_name.MyClassName you should do this instead:

JNIEnv* env;
android->activity->vm->AttachCurrentThread(&env, nullptr);

jclass native_activity_class = env->GetObjectClass(android->activity->clazz);
jmethodID get_class_loader = env->GetMethodID(native_activity_class, "getClassLoader", "()Ljava/lang/ClassLoader;");
jobject class_loader_object = env->CallObjectMethod(android->activity->clazz, get_class_loader);
jclass class_loader = env->FindClass("java/lang/ClassLoader");
jmethodID load_class = env->GetMethodID(class_loader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
jstring class_name = env->NewStringUTF("com.package_name.MyClassName");
jclass my_class = jclass(env->CallObjectMethod(class_loader_object, load_class, class_name));
env->DeleteLocalRef(class_name);

// my_class is what you're looking for

android->activity->vm->DetachCurrentThread();
Share this page:

See also how to:

How to call your native functions in Android NDK application from Java
How to open URL in web browser from Android NDK application with Java or native code
How to find all Clang arguments that used to build native code in Android Studio
Select target architectures in Android Studio build
The most simple example how to show a message box on Android application