2017-08-31 106 views
1

我写了一个JNI-Wrapper,但直到今天才在Linux上使用它。 现在我编译它的Windows和JVM崩溃在这个本地方法: 如果我删除ReleaseStringUTFCharsfree调用它也可以在Windows上工作,但它会很有趣,为什么这在Linux中,但不是在Windows中工作吗?(我使用Windows 10-64bit)。而从我的经验,这个电话是强制性的,一开始有一些内存泄漏(在Linux上)之前,我把它们正确地释放jni-wrapper在Windows上崩溃JVM

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); 
} 

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); 
// 

} 
} 

回答

1

的错误是因为你的可用内存的两倍。第一次 - 通过在onMessageReceived()之内调用ReleaseStringUTFChars(),第二次 - 在onMessageReceived()之外,您可以在每个发布的指针上调用free()

重要
你不需要的Java环境(调用的方法env->New*())内创建的对象手动释放内存。在你的情况下:

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

呼叫ReleaseStringUTFChars()是不适合在这里。仅当您创建从Java String使用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); 

javadoc的方法GetStringUTFChars()ReleaseStringUTFChars() - 你应该使用他们只在一起。

+0

感谢您的澄清,所以它似乎在Unix系统上不会导致崩溃时,我释放内存两次 – user2071938