【发布时间】:2011-06-30 22:12:54
【问题描述】:
在 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。
如何消除这种泄漏?
添加:
按照 Gregory 的建议,在 C++ 端处理 alloc/free,然后我定义了
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);
}
然后我在 JAVA 端使用 ByteBuffer
ByteBuffer myBuf = allocNative(LARGE_NUMBER);
释放它
freeNative(myBuf);
不幸的是,虽然它确实分配得很好,但它 a) 仍然保留根据 Debug.getNativeHeapAllocatedSize() 分配的内存 b) 导致错误
W/dalvikvm(26733): JNI: DeleteGlobalRef(0x462b05a0) failed to find entry (valid=1)
我现在完全糊涂了,我以为我至少理解了 C++ 方面的东西......为什么 free() 不返回内存?我对DeleteGlobalRef() 做错了什么?
【问题讨论】:
-
allocateDirect 分配保证不会被垃圾回收的内存。
-
那很好,但我可以手动释放它吗?具有分配内存的功能但不能相反的功能似乎很愚蠢。如果可以的话,我很乐意将它从 JNI 中解放出来。
-
Jon >
allocateDirect分配的内存保证不会被垃圾收集器重定位。但是一旦ByteBuffer被收集,本机内存就会被回收。 -
查看我编辑的关于
NewGlobalRef和DeleteGlobalRef的答案
标签: android memory-leaks java-native-interface bytebuffer