Native threads and JNI

It is well known a thread not generated from Java itself, like pthread_create on android, or a native activity, can’t find a JVM method by calling Java env’s FindClass. These method calls will return class not found (nullptr), even for prelude classes, like java.lang.String.

Turns out findClass method relies on a ClassLoader to find an specific jclass object. The solution, is simple, but subtle though.

Our native thread is not attached to any VM/Java Env and thus env->FindClass calls will fail. We need another way to find classes. And what class has a FindClass method ? Well, no other class does. But a ClassLoader exposes a loadClass method, which indirectly calls findClass and many other methods. Simply enough, we need to obtain a reference ClassLoader, being the most obvious java code to be: object.getClass().getClassLoader().

In my case, I get such class loader from the call to v8 initialisation. This method is public native void InitializeV8();. In native:

    Java_com_spellington_task_TaskRunnerInstance_InitializeV8(JNIEnv *env, jobject obj) {


        // obj if implicit this on java call to the native method.
        auto rc = env->GetObjectClass(obj);

        // obj.getClass()
        jclass clazz = env->GetObjectClass(rc);    

        // find getClassLoader method
        jmethodID getClassLoaderMethod = env->GetMethodID(clazz,

        // obtain class' ClassLoader reference.
        jobject objClassLoader = env->CallObjectMethod(rc, getClassLoaderMethod);     

        // protect this ref from GC ! This is mandatory. 
        //   objClassLoader must be stored somewhere else for later usage
        objClassLoader = env->NewGlobalRef(objClassLoader);

        // ClassLoader class
        jclass objClassLoaderClass = env->FindClass("java/lang/ClassLoader");
        // loadClass reference.
        //   Must be stored somewhere else for later usage.
        jmethodID loadClassMethod = env->GetMethodID(

This code just got a reference to a valid ClassLoader and a methodID to its loadClass method. Now we have an alternative to just calling findClass:

const char* const className = "com/spellington/HCSurfaceView";

auto clazz = env->FindClass(className);

// if findClass failed, try the ClassLoader alternative. 
// This will be true in two different scenarios:
//    + className, effectively does not exist.
//    + a native thread calls into JNI
if (clazz==nullptr) {
    // findClass alternative based on our ClassLoader
    clazz = static_cast<jclass>(

// if clazz is nullptr, there another two different scenarios:
//    + most likely, className is not a valid fully qualified class name.
//    + a native thread is trying to find a class which does not exist in the ClassLoader,
//        but might exist on another ClassLoader. This is likely if and only if your app
//        has customs ClassLoader instances. 

When using mixed Java/native thread, or just calling JNI in a multithread environment, you might want to pay attention to Java VM’s AttachCurrentThread method… But that’s another story.

Published by ibon

Chocolate engineer, software eater. Cool stuff at Past: Workday, Platochat, SdkBox, Chukong, Ludei.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: