JNI: Does C++ calls Java asynchronous?
<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>