В Android прямой ByteBuffer никогда не освобождает свою память, даже при вызове System.gc ().
Пример: делаю
Log.v("?", Long.toString(Debug.getNativeHeapAllocatedSize()));
ByteBuffer buffer = allocateDirect(LARGE_NUMBER);
buffer=null;
System.gc();
Log.v("?", Long.toString(Debug.getNativeHeapAllocatedSize()));
дает два числа в журнале, второе из которых как минимум на LARGE_NUMBER больше первого.
Как мне избавиться от этой утечки?
Добавлено:
Следуя предложению Грегори обрабатывать alloc / free на стороне C ++, я затем определил
JNIEXPORT jobject JNICALL Java_com_foo_bar_allocNative(JNIEnv* env, jlong size)
{
void* buffer = malloc(size);
jobject directBuffer = env->NewDirectByteBuffer(buffer, size);
jobject globalRef = env->NewGlobalRef(directBuffer);
return globalRef;
}
JNIEXPORT void JNICALL Java_com_foo_bar_freeNative(JNIEnv* env, jobject globalRef)
{
void *buffer = env->GetDirectBufferAddress(globalRef);
free(buffer);
env->DeleteGlobalRef(globalRef);
}
Затем я получаю свой ByteBuffer на стороне JAVA с помощью
ByteBuffer myBuf = allocNative(LARGE_NUMBER);
и освободи его с помощью
freeNative(myBuf);
К сожалению, несмотря на то, что он выделяет нормально, он а) по-прежнему сохраняет выделенную память в соответствии с Debug.getNativeHeapAllocatedSize()
и б) приводит к ошибке
W/dalvikvm(26733): JNI: DeleteGlobalRef(0x462b05a0) failed to find entry (valid=1)
Я сейчас полностью запутался, я думал, что, по крайней мере, понял сторону С ++ ... Почему free () не возвращает память? А что я делаю не так с DeleteGlobalRef()
?
allocateDirect
выделяет память, которая гарантированно не будет перемещена сборщиком мусора. Но как толькоByteBuffer
будет собран, будет возвращена собственная память. - person Gregory Pakosz   schedule 21.02.2011NewGlobalRef
иDeleteGlobalRef
- person Gregory Pakosz   schedule 21.02.2011