Android では、System.gc() を呼び出した場合でも、直接 ByteBuffer がメモリを解放するようには見えません。
例:やっている
Log.v("?", Long.toString(Debug.getNativeHeapAllocatedSize()));
ByteBuffer buffer = allocateDirect(LARGE_NUMBER);
buffer=null;
System.gc();
Log.v("?", Long.toString(Debug.getNativeHeapAllocatedSize()));
は、ログに 2 つの数値を示します。2 番目の数値は、最初の数値よりも少なくとも LARGE_NUMBER 大きくなります。
どうすればこの漏れを取り除くことができますか?
追加した:
C++ 側で alloc/free を処理するという Gregory の提案に従って、次に定義しました。
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()
ますか?