2017-08-31 6 views
1

J'ai écrit un JNI-Wrapper mais je l'ai utilisé jusqu'à aujourd'hui uniquement sous Linux. Maintenant, je l'ai compilé pour Windows et les plantages JVM dans ces méthodes natives: Si je supprime les appels ReleaseStringUTFChars et free il fonctionne également sur Windows, mais il serait intéressant de savoir pourquoi cela fonctionne sous Linux, mais pas dans Windows? (J'utilise Windows 10-64 bits). Et de mon expérience ce appels sont obligatoires, a obtenu des fuites de mémoire (sous Linux) au début avant que je les ai libérés correctementjni-wrapper bloque la JVM sous Windows

void onMessageReceived(char* topic, char* timestamp, char* id, char* value) { 
JNIEnv * g_env; 
int getEnvStat = (*g_vm)->GetEnv(g_vm, (void **) &g_env, JNI_VERSION_1_8); 
if (getEnvStat == JNI_EDETACHED) { 
    if ((*g_vm)->AttachCurrentThread(g_vm, (void **) &g_env, NULL) != 0) { 
     puts("Failed to attach"); 
     fflush(stdout); 
    } 
} 

if (methodHandleMessage) { 
} else { 
    jclass clazz = (*g_env)->GetObjectClass(g_env, store_callback); 
    methodHandleMessage = (*g_env)->GetMethodID(g_env, clazz, "handleMessage", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); 
} 
jstring j_topic = (*g_env)->NewStringUTF(g_env, topic); 
jstring j_timestamp = (*g_env)->NewStringUTF(g_env, timestamp); 
jstring j_value = (*g_env)->NewStringUTF(g_env, value); 
jstring j_id = (*g_env)->NewStringUTF(g_env, id); 


(*g_env)->CallVoidMethod(g_env, store_callback, methodHandleMessage, j_topic, j_timestamp, j_id, j_value); 

//HERE IS THE PROBLEM: 
(*g_env)->ReleaseStringUTFChars(g_env, j_topic, topic); 
(*g_env)->ReleaseStringUTFChars(g_env, j_timestamp, timestamp); 
(*g_env)->ReleaseStringUTFChars(g_env, j_value, value); 
(*g_env)->ReleaseStringUTFChars(g_env, j_id, id); 
// 

(*g_vm)->DetachCurrentThread(g_vm); 
} 

et

void rep_actor(zsock_t *pipe, void *args) { 
zsock_signal(pipe, 0); 
while (!zsys_interrupted) { 
    char* timestamp; 
    char* sender; 
    char* command; 
    char* message; 

    zsock_recv(reply, "ssss", &timestamp, &sender, &command, &message); 

    char* result = onRequestReceived(timestamp, sender, command, message); 
    zsock_send(reply, "s", result); 

//HERE IS THE PROBLEM: 

    free(timestamp); 
    free(sender); 
    free(command); 
    free(message); 
    free(result); 
// 

} 
} 

Répondre

1

L'erreur se produit parce que vous libérer de la mémoire deux fois. Première fois - en appelant ReleaseStringUTFChars() à l'intérieur de onMessageReceived(), deuxième - en dehors de onMessageReceived() vous appelez free() sur chaque pointeur libéré.

Important
Vous n'avez pas besoin de libérer la mémoire manuellement pour les objets créés à l'intérieur de java ambience (appeler des méthodes env->New*()). Dans votre cas:

// j_topic - it's a pointer for object inside of java heap 
// garbage collector will free this memory 
jstring j_topic = env->NewStringUTF(topic); 

Call of ReleaseStringUTFChars() est inapropriée ici. Cela utilisé uniquement lorsque vous créez chaîne native de java String utilisant GetStringUTFChars():

// j_topic - string inside of java heap 
const char* native_str = env->GetStringUTFChars(j_topic, isCopy); 

// your logic for native_str array 

// informs the VM that the native code no longer needs access to native_str 
env->ReleaseStringUTFChars(j_topic, native_str); 

Regardez javadoc pour les méthodes GetStringUTFChars() et ReleaseStringUTFChars() - vous devez utiliser seulement ils ensemble.

+0

je vous remercie pour la clarification, il semble donc sur un système Unix qu'il ne provoque pas un plantage lorsque je libère de la mémoire deux fois – user2071938