title: JNI: Does C++ calls Java asynchronous?
body: <p>I'm trying to call some java classes from c++ code by using the JNI. Today I experienced a very strange behaviour in my programm. I suspect that the c++ code is not wait until the java side finished it's work and I don't know why.</p>
  
  <p>The C++ code (in a shared object library) is running in it's own C++ thread. It is using a existing JavaVM of a java app that is already up and running. The references to the VM and the ClassLoader where fetched while the java application was loading the shared object library in JNI_Onload. Here I call the java method of a java object I created with JNI in the C++ thread:</p>
  
  <pre><code>env-&gt;CallVoidMethod(javaClassObject, javaReceiveMethod, intParam, byteParam, objectParam);
  uint32_t applicationSideResponseCode = getResponseCode(objectClass, objectParam, env);
  resp.setResponseCode(applicationSideResponseCode);
  std::string applicationData = getApplicationData(serviceResultClass, serviceResultObject, env);
  resp.setData(applicationData);
  </code></pre>
  
  <p>The Java <code>javaReceiveMethod</code> is accessing the database and fetching some <code>applicationData</code> which is stored in the <code>objectParam</code>. Unfortunately the C++ code fetched the applicationData before the java class completed it's work. applicationData is <code>null</code> and the JNI crashes. Why? I can't find any documentation of Oracle stating that CallVoidMethod is executed asynchronous?</p>
  
  <p><strong>Edit</strong></p>
  
  <p>I verified that no exception has occured on the java method. Everything seems fine, except that Java is still busy while C++ is trying to access the data.</p>
  
  <p><strong>Edit</strong></p>
  
  <p>I can confirm that if I debug the java application two threads are shown. On main thread, that is executing <code>javaReceiveMethod</code> and one thread that is fetching the <code>applicationData</code>. How can I solve this problem? Idle in the second thread until the data is available?</p>
  
  <p><strong>Edit</strong></p>
  
  <p>In my C++ code I'm creating a new object of the java class that I want to call:</p>
  
  <pre><code>jmethodID javaClassConstructor= env-&gt;GetMethodID(javaClass, "&lt;init&gt;", "()V");
                      jobject serviceObject = env-&gt;NewObject(javaClass, serviceConstructor);
  jobject javaClassObject = env-&gt;NewObject(javaClass, javaClassConstructor);
  </code></pre>
  
  <p>After that I call the code as shown above. After more debugging I can say that the method is called in a thread named <code>Thread-2</code> (I don't know if that is the c++ thread or a new one from JNI). It is definitely not the java main thread. However the work of the method is interrupted. That means If I debug the code, I can see that the data would be set soon but in the next debug step the <code>getApplicationData</code> method is executed (which can only occur if c++ is calling it).</p>
  
  <p><strong>Edit</strong>
  The Java method I call:</p>
  
  <pre><code>public int receive(int methodId, byte[] data, ServiceResult result){
          log.info("java enter methodID = " + methodId + ", data= " + data);  
  
          long responseCode = SEC_ERR_CODE_SUCCESS;
  
          JavaMessageProto msg;
          try {
              msg = JavaMessageProto (data);
              log.info("principal: " + msg.getPrincipal());       
              JavaMessage message = new JavaMessage (msg);
  
              if(methodId == GET_LISTS){
                  //this is shown in console
                  System.out.println("get lists");                
                  responseCode = getLists(message);
                  //this point is not reached 
                  log.info("leave");  
              }           
              //[... different method calls here...]
              if(responseCode != SEC_ERR_CODE_METHOD_NOT_IMPLEMENTED){
                  //ToDoListMessageProto response = message.getProtoBuf();
                  JavaMessageProto response = JavaMessageProto.newBuilder()   
                          .setToken(message.getToken())
                          .setPrincipal(message.getPrincipal()).build();
                  byte[] res = response.toByteArray();                
                  result.setApplicationData(response.toByteArray());
              }
              else{
                  result.setApplicationData("");
              }
  
          } catch (InvalidProtocolBufferException e) {
              responseCode = SEC_ERR_CODE_DATA_CORRUPTED;
              log.severe("Error: Could not parse Client message." + e.getMessage());
          }               
  
          result.setResponseCode((int)responseCode);
          return 0;
      }
  </code></pre>
  
  <p>The second method is</p>
  
  <pre><code>public long getLists(JavaMessage message) {
  log.info("getLists enter");
  
  String principal = message.getPrincipal();
  String token = message.getToken();  
  
  if(principal == null || principal.isEmpty()){           
      return SEC_ERR_CODE_PRINCIPAL_EMPTY;
  }       
  if(token == null || token.isEmpty()){       
      return SEC_ERR_CODE_NO_AUTHENTICATION;
  }       
  
  //get user object for authorization
  SubjectManager manager = new SubjectManager();
  Subject user = manager.getSubject();
  
  user.setPrincipal(principal);
  long result = user.isAuthenticated(token);
  if(result != SEC_ERR_CODE_SUCCESS){
      return result;
  }   
  try {
      //fetch all user list names and ids         
      ToDoListDAO db = new ToDoListDAO();     
      Connection conn = db.getConnection();       
      log.info( principal + " is authenticated");
      result = db.getLists(conn, message);
      //this is printed
      log.info( principal + " is authenticated");         
      conn.close();   //no exception here
      message.addId("testentry");
      //this not          
      log.info("Fetched lists finished for " + principal);
  } catch (SQLException e) {  
      log.severe("SQLException:" + e.getMessage());
      result = SEC_ERR_CODE_DATABASE_ERROR;
  }           
  
  return result;
  }
  </code></pre>