请注意我没有内存泄漏。我的问题是关于一个更微妙的问题。
我最近写了一个Android应用程序来进行图像处理。图像作为位图加载,然后以像素复制,以使用大量内存的方式处理(考虑浮点表示和填充中的傅里叶变换),然后转换回位图并保存。
问题是,至少通过Android OS 2.3,总内存限制(通常为16MB)结合了java和(外部存储)位图,并且java高水位标记不会下降(我能辨别)甚至当内存空闲(成功GC)时,这意味着当我去分配最终的Bitmap时,我经常“内存不足”,即使在那一点上我已经释放了(和GC'd)大部分空间。即,我从来不需要一次完整的16MB,但是Bitmaps留下的空间似乎是16MB减去MAX历史java堆的使用量(与当前使用情况相反)。
我看了一位Android开发人员关于内存问题的技术演讲,他暗示这个问题已经在操作系统的后续版本中得到修复(他们将Bitmap内存移动到java堆空间中),但与此同时大多数想要使用我的应用程序的人正在运行2.2或2.3。
长话短说,我想知道java堆是否会被压缩(实际上是去碎片),以便高水位标记缩小(如果是这样,如何实现它)?
如果没有,那么有人有另外一个建议如何处理这个问题吗?
答案 0 :(得分:1)
长话短说,我想知道java堆是否会被压缩(实际上是去碎片),以便高水位标记缩小(如果是这样,如何实现它)?
不管它的行为是什么,它肯定不在你的控制之下。
如果没有,那么有人有另外一个建议如何处理这个问题吗?
理想情况下,重复使用自己的Bitmaps
。您没有指出“以一种使用大量内存的方式处理”的确是什么。但是,如果它不会更改图像的尺寸或位深度,请将数据复制回原始Bitmap
,而不是分配新的数据,如果可以的话。
Android 2.x上的图像处理是我可以看到使用多个进程证明合理性的少数几个地方之一。您将增加在进程之间处理图像数据的开销,但另一个进程有自己的堆(Java和本机),因此这可能会为您提供更多“肘部空间”。
答案 1 :(得分:1)
到目前为止,没有迹象表明有任何方法可以压缩内存。
这是我的解决方法,它不是最理想的,但比之前的行为要好得多:
我现在故意在我处理时保留原始Bitmap,然后使用recycle()并将其null和GC(),但直到分配我的输出Bitmap之前。
这样做是保留外部(Bitmap)空间,并导致我的应用程序耗尽java堆(在处理期间,在调用recycle()之前),我至少可以通过重试较小的图像来捕获和处理。 (之前,在我试图保存之前,一切似乎都很好,但到那时已经太晚了,无法恢复。)
从技术上讲,这会将我的最大图像大小限制为小于我应该能够分配的内存(因为我需要在堆中保留空间并且同时在外部保留空间,而实际上我从不需要两者一起),但是至少我仍然可以处理合理的图像尺寸。
以前发生的事情是我会尽早释放并回收Bitmap,它允许java堆上的高水位基本消耗掉我的所有内存分配,这意味着从那时起我无法打开或创建更多根本就是位图(有时缩小尺寸除外)。
Imo,这是android处理Bitmap内存的一个主要错误,但我相信它已在新版本的操作系统中得到修复,所以希望我可以在操作系统发布的条件下禁用此解决方法。答案 2 :(得分:0)
我假设您已经致电Bitmap.recycle()
,但这是我记忆中唯一没有谈过的事情。