首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JNI代码中的内存泄漏

问JNI代码中的内存泄漏
EN

Stack Overflow用户
提问于 2017-04-27 06:52:11
回答 1查看 743关注 0票数 2

下面是连接C和Java进程之间Linux的JNI代码。虽然我已经发布了所有的ArrayElements,但是顶级命令的VIRT显示出了巨大的价值。最大堆大小设置为2GB,但顶部显示执行100小时后VIRT为10 2GB。在我看来,这似乎是内存泄漏,但我不知道JNI代码的哪一部分是造成问题的原因。如果有人能帮我点忙就好了。谢谢。

我的JDK版本是1.8.0_91

这是我写的mq_receive方法

代码语言:javascript
复制
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方法

代码语言:javascript
复制
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;

}
EN

回答 1

Stack Overflow用户

发布于 2017-04-27 07:32:58

这是旗子的意思作为最后一个参数传递给ReleaseByteArrayElements:

模式标志的可能设置为: 更新Java堆上的数据。释放副本所使用的空间。 JNI_COMMIT更新Java堆上的数据。不要释放副本所使用的空间。 JNI_ABORT不更新Java堆上的数据。释放副本所使用的空间。 “0”模式标志是发布调用最安全的选择。无论数据的副本是否被更改,堆都会使用副本进行更新,并且没有泄漏。

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

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

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

以上假设缓冲区是副本,而不是固定引用。我认为这是一个副本,但是,因为否则不会有泄漏。您可以通过将&isCopy参数传递给GetByteArrayElements来查找。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43650572

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档