title: Calling JAVA class member from Native C/C++ code
body: <p>I'm writing an OpenGL C/C++ application which i'm porting to Android through Android NDK, JNI support. I'm having difficulties executing code from JAVA callback signaled from native.</p>
  
  <p>Here is the code:</p>
  
  <pre><code>class OpenGLSurfaceView extends GLSurfaceView 
  {
  …
       public OpenGLSurfaceView(Context context, int deviceWidth, int deviceHeight) 
      {
          super(context);
          nativeObj = new NativeLib();
          mRenderer = new OpenGLRenderer(context, nativeObj, deviceWidth, deviceHeight);
          setRenderer(mRenderer);
          setRenderMode(RENDERMODE_WHEN_DIRTY);
      }
  …
      private void CallBack()
      {
          // force redraw
          requestRender();
      }
  }
  
  
  class OpenGLRenderer implements GLSurfaceView.Renderer 
  {
      …
  public void onSurfaceCreated(GL10 gl, EGLConfig config) 
      {
          nativeObj.init(…);
          nativeObj.cachejavaobject(JNIEnv *env, jobject obj); // for caching obj on native side
      }
  
      public void onSurfaceChanged(GL10 gl, int w, int h) 
      {
      }
  
      public void onDrawFrame(GL10 gl) 
      {
          nativeObj.draw(…);
      }
  }
  </code></pre>
  
  <p>And in native code i have a function texturesLoaded() that is signaled when some textures are loaded completely on another thread and i need to force a refresh from nativeLib.draw(…) on the JAVA side. Here is how i do it :</p>
  
  <p>I cache the JavaVM, jClass, jMethodID on JNI_OnLoad, and gJObjectCached</p>
  
  <pre><code>JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
  {
  gJVM = jvm;  // cache the JavaVM pointer
  
  LogNativeToAndroidExt("JNILOAD!!!!!!!!!!");
  JNIEnv *env;
  int status = gJVM-&gt;GetEnv((void **)&amp;env, JNI_VERSION_1_6);
  if(status &lt; 0)
  {
      LogNativeToAndroidExt("Failed to get JNI environment, assuming native thread");
      status = gJVM-&gt;AttachCurrentThread(&amp;env, NULL);
      if(status &lt; 0)
      {
          LogNativeToAndroidExt("callback_handler: failed to attach current thread");
          return JNI_ERR;
      }
  }
  
  gJClass = env-&gt;FindClass("com/android/newlineactivity/NewLineGLSurfaceView");
  if(gJClass == NULL)
  {
      LogNativeToAndroidExt("Can't find Java class.");
      return JNI_ERR;
  }
  
  gJMethodID = env-&gt;GetMethodID(gJClass, "callback", "()V");
  if(gJMethodID == NULL)
  {
      LogNativeToAndroidExt("Can't find Java method void callback()");
      return JNI_ERR;
  }
  
  return JNI_VERSION_1_6;
  </code></pre>
  
  <p>}</p>
  
  <pre><code>JNIEXPORT void Java_com_android_OpenGL_NativeLib_cachejavaobject(JNIEnv* env, jobject obj)
  {
      // cache the java object
      gJObjectCached = obj;
  ...
  }
  </code></pre>
  
  <p>and then on texturesLoaded() i do :</p>
  
  <pre><code>void texturesLoaded()
  {
      // Cannot share a JNIEnv between threads. You should share the JavaVM, and use JavaVM-&gt;GetEnv to discover the thread's JNIEnv
      JNIEnv *env = NULL;
      int status = gJVM-&gt;GetEnv((void **)&amp;env, JNI_VERSION_1_6);
      if(status &lt; 0)
      {
          LogNativeToAndroidExt("callback_handler: failed to get JNI environment, assuming native thread");
          status = gJVM-&gt;AttachCurrentThread(&amp;env, NULL);
          if(status &lt; 0)
          {
              LogNativeToAndroidExt("callback_handler: failed to attach current thread");
              return;
          }
      }
  
      LogNativeToAndroidExt("Calling JAVA method from NATIVE C/C++");
      env-&gt;CallVoidMethod(gJObjectCached, gJMethodID);
      LogNativeToAndroidExt("DONE!!!");
  }
  </code></pre>
  
  <p>Result… from native side i get the class, i get the method, method gets called, but when it reaches/calls requestRender() inside(or trying to access any other member method of GLSurfaceView it crashes!)</p>
  
  <p>I cannot try with CallStaticVoidMethod(gJClass, gjMethodID); because then i don't have access to requestRender();</p>
  
  <p>Any ideas or opinions, maybe i'm doing something wrong here.</p>
  
  <p>Thanks</p>