【问题标题】:Memory Leak in JNI layer for unsigned char array无符号字符数组的 JNI 层中的内存泄漏
【发布时间】:2012-02-29 05:16:44
【问题描述】:

我有一个 JNI 代码,用于从 java 调用 .Net API。

在一次调用中,我将一个 java 字节数组转换为一个用于 .Net 调用的无符号字符数组。

创建的 unsigned char 数组被包裹在一个 Java 对象上,在该 java 对象的 finalize 调用期间,我正在清除它。

但在连续运行时,内存只会不断增加,最终导致 OutOfMemoryException。

这里是创建无符号字符数组的代码

jbyte* messageBodyNativeJByteBuffer = env->GetByteArrayElements(jByteArrayValue,NULL);

        if(messageBodyNativeJByteBuffer == NULL){
            RaiseError(DNJNI_ERROR_ALLOCATE, "unsigned char array");
        }

        jsize arrayLength = env->GetArrayLength(jByteArrayValue);
        array<unsigned char>^ dataArray = gcnew array<unsigned char>(arrayLength);
        try{
            for(int i=0;i<arrayLength;i++){
                dataArray[i] = messageBodyNativeJByteBuffer[i];
            }
            return dataArray;
        }finally{
            // Release the UTF8 bytes
            cout << "Inside BuildByteArray finally block.";
            env->ReleaseByteArrayElements(jByteArrayValue, messageBodyNativeJByteBuffer,0);
            cout << "Inside BuildByteArray finally block - After delete messageBodyNativeJByteBuffer.";
            delete messageBodyNativeJByteBuffer;
            env->DeleteLocalRef(jByteArrayValue);
            cout << "Inside BuildByteArray finally block - After DeleteLocalRef jByteArrayValue.";
        }

还有清理电话,清除它


Object^ object = DotNETJNIInterface::NativeState::findState(identifier);
        //This if is I added recently to try deleting it, but does not help
    if(object->GetType()->ToString()->Equals("System.Byte[]")){
            array<unsigned char>^ toBeDeleted = dynamic_cast<array<unsigned char>^>(object);
            delete [] toBeDeleted;
            cout << "Deleted Byte Array by self::::";
    }
    DotNETJNIInterface::NativeState::removeState(identifier);

如果我遗漏了什么导致字节数组内存未被删除,请告诉我。

【问题讨论】:

    标签: java java-native-interface


    【解决方案1】:

    我可以看到几个问题:

    1. GetByteArrayElements() 返回的数组被ReleaseByteArrayElements() 清理,但你也在delete-ing 它。这是一个主要的禁忌,很可能会破坏堆。删除它,然后重试。

    2. 如果gcnew 抛出异常,GetByteArrayElements() 不会被调用,它分配的内存就会泄漏。

    从您的描述中也不清楚第二部分中清理代码的目的是什么,以及 OutOfMemory 异常是 Java 还是 .NET 异常。

    顺便说一句,JDK 有一个名为jmap 的不错的实用程序,可用于检查 JVM 堆并查看问题是否在于您的 Java 字节数组过多。

    【讨论】:

      猜你喜欢
      • 2013-09-11
      • 2017-06-19
      • 1970-01-01
      • 2017-01-09
      • 1970-01-01
      • 2014-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多