gpt4 book ai didi

java - JNI 代码中的内存泄漏

转载 作者:太空宇宙 更新时间:2023-11-03 23:19:46 26 4
gpt4 key购买 nike

下面是在 C 和 Java 进程之间桥接 Linux MQ 的 JNI 代码。虽然我已经释放了所有的 ArrayElements,但是 top 命令的 VIRT 仍然显示出巨大的值(value)。最大堆大小设置为 2GB,但在执行 100 小时后顶部显示 VIRT 为 10GB。对我来说这看起来像是内存泄漏,但是,我无法弄清楚是 JNI 代码的哪一部分导致了问题。如果有人可以帮助我,那就太好了。谢谢。

我的JDK版本是1.8.0_91

这是我写的mq_receive方法

JNIEXPORT int JNICALL Java_test_ipc_impl_LinuxMessageQueue_mq_1receive(
JNIEnv *env, jobject self, jint mqdes, jbyteArray buffer, jint msglen) {
jbyte* buf = (*env)->GetByteArrayElements(env, buffer, NULL);
if ((*env)->ExceptionCheck(env))
return -1;

struct timespec timeout;

clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += 1;

int size = mq_timedreceive(mqdes, (char*) buf, msglen, 0, &timeout);

if (size == -1) {
if (errno == ETIMEDOUT) {
size = 0;
} else {
perror("mq_receive fail");
}
} else {
(*env)->SetByteArrayRegion(env, buffer, 0, size, buf);
if ((*env)->ExceptionCheck(env))
return -1;
}

(*env)->ReleaseByteArrayElements(env, buffer, buf, JNI_COMMIT);
if ((*env)->ExceptionCheck(env))
return -1;

return size;
}

而且,这是我写的mq_send方法

JNIEXPORT void JNICALL Java_test_ipc_impl_LinuxMessageQueue_mq_1send(
JNIEnv *env, jobject self, jint mqdes, jbyteArray buffer, jint msglen) {
jbyte* buf = (*env)->GetByteArrayElements(env, buffer, NULL);
if ((*env)->ExceptionCheck(env))
return;

if (mq_send(mqdes, (char*) buf, msglen, 0) == -1) {
perror("mq_send fail");
}
(*env)->ReleaseByteArrayElements(env, buffer, buf, JNI_COMMIT);
if ((*env)->ExceptionCheck(env))
return;

}

最佳答案

Here's the meaning of the flags你传递给 ReleaseByteArrayElements 作为最后一个参数:

The possible settings of the mode flag are:

0 Update the data on the Java heap. Free the space used by the copy.

JNI_COMMIT Update the data on the Java heap. Do not free the space used by the copy.

JNI_ABORT Do not update the data on the Java heap. Free the space used by the copy.

The ‘0' mode flag is the safest choice for the Release call. Whether the copy of the data was changed or not, the heap is updated with the copy, and there are no leaks.

因此,在您的 mq_receive 函数中,调用 ReleaseByteArrayElements 并传递 0 作为最终参数。您不需要 SetByteArrayRegion 调用,因为数据将由 ReleaseByteArrayElements 复制回来。

在您的 mq_send 函数中,您可以传递 JNI_ABORT,因为您没有写入数组。

这应该在两种情况下释放缓冲区。

上面假设缓冲区是一个副本而不是固定引用。然而,我认为它是一个副本,否则就不会泄漏。您可以通过将 &isCopy 参数传递给 GetByteArrayElements 来找出答案。

关于java - JNI 代码中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43650572/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com