title: JNI GetMethodID cause error in native thread
body: <p>In android I use pthread_create to create a native thread , then in the Callback procedure ,call FindClass to get a Java class. but it does'nt work. I get tips from <a href="http://developer.android.com/guide/practices/jni.html#faq_FindClass" rel="nofollow noreferrer">android jni tips</a>
  I found the solution in <a href="https://stackoverflow.com/questions/13263340/findclass-from-any-thread-in-android-jni/16302771#16302771">FindClass from any thread in Android JNI</a></p>
  
  <p>I modify it for my project like this
  [edit]</p>
  
  <pre><code>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-&gt;FindClass("com/example/RandomClass");
      jclass classClass = env-&gt;GetObjectClass(randomClass);
      auto classLoaderClass = env-&gt;FindClass("java/lang/ClassLoader");
      auto getClassLoaderMethod = env-&gt;GetMethodID(classClass, "getClassLoader",
                                               "()Ljava/lang/ClassLoader;");
      gClassLoader = env-&gt;CallObjectMethod(randomClass, getClassLoaderMethod);
      gClassLoader = env-&gt;NewGlobalRef(gClassLoader);
      gFindClassMethod = env-&gt;GetMethodID(classLoaderClass, "loadClass",
                                      "(Ljava/lang/String;)Ljava/lang/Class;");
  
      //check. this is ok
      jclass cls = env-&gt;FindClass("com/example/data/DataTest");
      jmethodID methoID = env-&gt;GetMethodID(cls, "name", "()Ljava/lang/String;");
      LOG_INFO("cls is %p\n", cls);
  
      return JNI_VERSION_1_6;
  }
  
  JNIEnv* getEnv() {
      JNIEnv *env;
      int status = gJvm-&gt;GetEnv((void**)&amp;env, JNI_VERSION_1_6);
      if(status &lt; 0) {    
          status = gJvm-&gt;AttachCurrentThread(&amp;env, NULL);
          if(status &lt; 0) {        
          return nullptr;
          }
      }  
      return env;
  }
  
  
  jclass findClass(const char* name) {
       JNIEnv *env = getEnv();
       jclass resultClass = 0;
       if(env)
       {
          resultClass = env-&gt;FindClass(name);
          //it can not found class in native thread, use loadClass method
          if (!resultClass)
          {
              LOG_INFO("can not find the class");
              //return value is not null. 
              return static_cast&lt;jclass&gt;(env-&gt;CallObjectMethod(gClassLoader, gFindClassMethod, env-&gt;NewStringUTF(name))); 
          }
      }
      return resultClass;
  }
  .......
  //thread callback 
  void *proc(void *)
  {
    JNIEnv *env = getEnv();
    jclass cls = findClass("com/example/data/DataTest");
    if (cls)
    {
      LOG_INFO("GetMethodID");
      //crash
      jmethodID methodID = env-&gt;GetMethodID(cls, "name", "()Ljava/lang/String;"); 
      LOG_INFO("proc tag is %p\n", tag);
    }
  }
  .....
  pthread_create(&amp;handle, NULL, proc, 0);
  .....
  </code></pre>
  
  <p>program is exit at env->GetMethodID. I get this error: </p>
  
  <pre><code>Invalid indirect reference 0x40d8bb20 in decodeIndirectRef.
  </code></pre>
  
  <p>if i remove <code>resultClass = env-&gt;FindClass(name);</code>  from findClass, it's OK. "proc tag is " can be printed.  </p>
  
  <pre><code>//correct 
  jclass findClass(const char* name) {
       JNIEnv *env = getEnv();
       jclass resultClass = 0;
       if(env)
       {
          if (!resultClass)
          {
              return static_cast&lt;jclass&gt;(env-&gt;CallObjectMethod(gClassLoader, gFindClassMethod, env-&gt;NewStringUTF(name))); 
          }
      }
      return resultClass;
  }
  </code></pre>
  
  <p>any confilct between <code>env-&gt;FindClass(name);</code> and <code>env-&gt;CallObjectMethod to loadClass</code>?</p>
  
  <p>Is it a bug? What can be done to fix the problem?</p>