android – ByteBuffer不释放内存

android – ByteBuffer不释放内存,第1张

概述在 Android上,一个直接的ByteBuffer似乎并没有释放它的内存,甚至在调用System.gc()时也是如此. 例如:做 Log.v("?", Long.toString(Debug.getNativeHeapAllocatedSize()));ByteBuffer buffer = allocateDirect(LARGE_NUMBER);buffer=null;System.g 在 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()中做错了什么?

解决方法 没有泄漏.

ByteBuffer.allocateDirect()从本机堆/免费存储(认为malloc())分配内存,然后将其包装到ByteBuffer实例中.

当ByteBuffer实例收集垃圾内容时,回收本机内存(否则将泄漏本机内存).

您正在调用System.gc(),希望立即回收原生内存.但是,调用System.gc()只是一个请求,它解释了为什么你的第二个日志语句不会告诉你内存已经被释放:这是因为还没有!

在您的情况下,Java堆中的空闲内存显然足够,垃圾收集器决定不执行任何 *** 作:因此,不可访问的ByteBuffer实例尚未收集,其终结器不会运行,并且本机内存不会被释放.

此外,请注意JVM中的这个bug(不知道它如何适用于Dalvik),其中大量分配的直接缓冲区导致不可恢复的OutOfMemoryError.

你对JNI做的事情做了评论.这实际上是可能的,你可以实现以下几点:

>发布本机ByteBuffer allocateNative(long size)入口点:

调用voID * buffer = malloc(size)来分配本地内存
>将新分配的数组转换为ByteBuffer实例,并调用(* env) – > NewDirectByteBuffer(env,buffer,size);
>使用(* env) – > NewGlobalRef(env,directBuffer)将ByteBuffer本地引用转换为全局引用.

>发布一个native voID disposeNative(ByteBuffer buffer)入口点:

在*(env) – > GetDirectBufferAddress(env,directBuffer)返回的直接缓冲区地址上调用free();
>使用(* env) – > DeleteGlobalRef(env,directBuffer)删除全局参考;

一旦你在缓冲区上调用了disposeNative,那么你不应该使用引用,所以它可能非常容易出错.重新考虑您是否真的需要对分配模式进行明确的控制.

忘记我关于全局参考的内容.实际上,全局引用是一种在本机代码中存储引用的方法(如全局变量),以便进一步调用JNI方法可以使用该引用.所以你会有:

>从Java中调用本地方法foo(),该方法从本地引用(通过从本机创建对象获取)创建全局引用,并将其存储在本机全局变量(作为作业)中)
再次从Java中调用本地方法bar(),它获取foo()存储的jobject并进一步处理它
>最后,仍然从Java,最后一次调用native baz()会删除全局引用

对困惑感到抱歉.

总结

以上是内存溢出为你收集整理的android – ByteBuffer不释放内存全部内容,希望文章能够帮你解决android – ByteBuffer不释放内存所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1131841.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-30
下一篇 2022-05-30

发表评论

登录后才能评论

评论列表(0条)

保存