JNI层中的内存泄漏,用于unsigned char数组

时间:2012-02-29 05:16:45

标签: java java-native-interface

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

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

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

但是在连续运行时,内存只会继续构建,最终会以OutOfMemoryException结束。

以下是创建unsigned char数组

的代码
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);

如果我遗漏了导致字节数组内存不被删除的内容,请告诉我。

1 个答案:

答案 0 :(得分:2)

我可以看到几个问题:

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

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

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

    顺便说一句,JDK有一个很好的实用程序叫jmap,它可以用来检查JVM堆,看看问题是你有太多的Java字节数组。