Утечка памяти в слое JNI для массива без знака - PullRequest
1 голос
/ 29 февраля 2012

У меня есть код JNI, который используется для выполнения вызовов .Net API из Java.

В одном вызове я преобразую байтовый массив java в массив без знака, который используется для вызова .Net.

Созданный массив unsigned char помещается в Java-объект, и во время вызова finalize этого java-объекта я очищаю его.

Но при выполнении непрерывного прогона память просто продолжает собираться, что в итоге заканчивается 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 Ответ

2 голосов
/ 02 марта 2012

Я вижу несколько проблем:

  1. Массив, возвращаемый GetByteArrayElements(), очищается ReleaseByteArrayElements(), но вы также delete -ing его. Это главное нет-нет и вполне может испортить кучу. Удалите это и попробуйте снова.

  2. Если gcnew выдает исключение, GetByteArrayElements() не вызывается, и выделенная им память протекает.

Из вашего описания также неясно, какова цель кода очистки во втором разделе и является ли исключение OutOfMemory исключением Java или .NET.

Кроме того, в JDK есть хорошая утилита под названием jmap, которую можно использовать для проверки кучи JVM и определения, не в том ли у вас слишком много байтовых массивов Java.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...