【问题标题】:JNI memory leak from byte array来自字节数组的 JNI 内存泄漏
【发布时间】:2013-09-11 03:58:16
【问题描述】:

我有一个 java 程序多次调用本机函数。我的问题是这个函数有内存泄漏,我为摆脱它所做的一切都会导致内存转储。任何帮助将不胜感激。

这是我的代码

JNIEXPORT void JNICALL Java_class_method_getInput
(JNIEnv *env, jobject obj)
{
    if (inputIsAvailable)
    {

    int size = getBufferCurrentIndex();
    size -= getBufferReadIndex();
    size *= 2;

    char *finalSendArray = new char[size];

    getCommand(finalSendArray);

    jbyteArray byteArray = env->NewByteArray(size / 2);
    env->SetByteArrayRegion(byteArray, 0, size / 2, (jbyte*) finalSendArray);

    while(methodID == 0)
    {
        jclass cls = env->GetObjectClass(obj);
        methodID = env->GetMethodID(cls, "setCommand", "([B)V" );
    }

    env->CallVoidMethod(obj, methodID, byteArray);

    //env->ReleaseByteArrayElements(byteArray, (jbyte*) finalSendArray, JNI_ABORT);

我的问题是上面的 ^ 代码如果未注释会导致内存转储,如果未取消注释,我的程序会在几分钟内耗尽内存

    env->DeleteLocalRef(byteArray);
    delete[] finalSendArray;
    }
}

任何帮助将不胜感激。谢谢!

【问题讨论】:

  • 先释放byteArray,再删除底层内存?
  • 我的回复解决了您的问题吗?如果确实如此,请将其标记为正确。你为什么要在 C 中做这一切? getCommand 是做什么的?可以在java中完成吗? jni 很贵。
  • @JustinDanielson 嘿抱歉这么久才回复,我的某个地方仍有泄漏。我不确定在哪里。我正在使用 c++,因为我只是在重用已经构建的代码。它可以用 Java 重写,但我更愿意将它保留在当前的实现中。
  • @KerrekSB 我希望这有效......但不幸的是它没有。
  • 很抱歉。我真的不知道;我能给出的唯一建议是仔细阅读 JNI 规范并确保您了解所有不同的生命周期和依赖关系。

标签: java c++ memory-leaks java-native-interface


【解决方案1】:

如果您使用 JNI_ABORT 参数,ReleaseByteArrayElements 也会释放内存。因此,当您稍后执行删除和释放时,其中一个指针指向导致转储的未初始化内存。

其中一个会起作用,我相当肯定它是第一个起作用的。

env->ReleaseByteArrayElements(byteArray, (jbyte*) finalSendArray, JNI_ABORT);
delete[] finalSendArray;

如果第一次失败,试试这个。

env->ReleaseByteArrayElements(byteArray, (jbyte*) finalSendArray, JNI_ABORT);
env->DeleteLocalRef(byteArray);

在 ReleaseByteArrayElements 之后添加一个 print 语句,你会看到你的程序正在执行超出该命令并在 Release/Delete[] 上崩溃

Search for "Table 4-10 Primitive Array Release Modes"

【讨论】:

  • 第一个导致code ***检测到glibc *** /usr/lib/jvm/java-7-openjdk-amd64/bin/java:双重释放或损坏(fasttop): 0x00007fb8a4001030 *** code 第二个我还有内存泄漏。我将确保内存泄漏确实存在
  • 它可能在 getCommand 中。它现在不再在同一个地方崩溃了吗?
  • 日志文件指向函数 SetByteArrayRegion 并抛出错误 bad_alloc
  • 您的分配是否会失败?(返回 null)。您为 JVM 分配了多少内存?在调用 setByteArrayRegion 之前检查这些指针中的任何一个是否为 NULL。如果是,打印出来,写入日志,或者抛出异常。 bad_alloc 是否会在第一个 JNI 调用中抛出?还是一堆之后?(内存泄漏)
  • 可能是堆内存不足。看看这个来增加它,stackoverflow.com/questions/1565388/increase-heap-size-in-java
猜你喜欢
  • 1970-01-01
  • 2017-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多