On Android, a direct ByteBuffer does not ever seem to release its memory, not even when calling System.gc().
Example: doing
Log.v("?", Long.toString(Debug.getNativeHeapAllocatedSize()));
ByteBuffer buffer = allocateDirect(LARGE_NUMBER);
buffer=null;
System.gc();
Log.v("?", Long.toString(Debug.getNativeHeapAllocatedSize()));
gives two numbers in the log, the second one being at least LARGE_NUMBER larger than the first.
How do I get rid of this leak?
Added:
Following the suggestion by Gregory to handle alloc/free on the C++ side, I then defined
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);
}
I then get my ByteBuffer on the JAVA side with
ByteBuffer myBuf = allocNative(LARGE_NUMBER);
and free it with
freeNative(myBuf);
Unfortunately, while it does allocate fine, it a) still keeps the memory allocated according to Debug.getNativeHeapAllocatedSize()
and b) leads to an error
W/dalvikvm(26733): JNI: DeleteGlobalRef(0x462b05a0) failed to find entry (valid=1)
I am now thoroughly confused, I thought I at least understood the C++ side of things... Why is free() not returning the memory? And what am I doing wrong with the DeleteGlobalRef()
?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…