Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/204.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 有没有办法压缩安卓系统的内存以降低高水位?_Android_Memory_Memory Management_Out Of Memory - Fatal编程技术网

Android 有没有办法压缩安卓系统的内存以降低高水位?

Android 有没有办法压缩安卓系统的内存以降低高水位?,android,memory,memory-management,out-of-memory,Android,Memory,Memory Management,Out Of Memory,请注意,我没有内存泄漏。我的问题是关于一个更微妙的问题 我最近写了一个android应用程序,它可以进行图像处理。图像作为位图加载,然后以像素为单位复制,以使用大量内存的方式进行处理(想想浮点表示中的傅立叶变换之类的东西),然后转换回位图并保存 问题是,至少通过android OS 2.3,总内存限制(通常为16MB)是java和(外部存储的)位图的组合,java高水位线不会下降(我可以看出),即使内存空闲(成功GC'd),这意味着当我分配最终位图时,我经常“内存不足”即使到那时,我已经释放了(

请注意,我没有内存泄漏。我的问题是关于一个更微妙的问题

我最近写了一个android应用程序,它可以进行图像处理。图像作为位图加载,然后以像素为单位复制,以使用大量内存的方式进行处理(想想浮点表示中的傅立叶变换之类的东西),然后转换回位图并保存

问题是,至少通过android OS 2.3,总内存限制(通常为16MB)是java和(外部存储的)位图的组合,java高水位线不会下降(我可以看出),即使内存空闲(成功GC'd),这意味着当我分配最终位图时,我经常“内存不足”即使到那时,我已经释放了(和GC’d)大部分空间。也就是说,我永远不需要一次使用全部16MB,但位图的剩余空间似乎是16MB减去最大历史java堆使用量(与当前使用量相反)

我观看了一位android开发者关于内存问题的技术演讲,他暗示这个问题已经在后续版本的操作系统中得到了解决(他们将位图内存移到了java堆空间),但与此同时,大多数想要使用我的应用程序的人都在运行2.2或2.3

长话短说,我想知道java堆是否曾经被压缩(实际上是去碎片化),从而使高水位线收缩(如果是这样,如何实现)

如果没有,那么有人对如何处理这个问题有其他建议吗

长话短说,我想知道java堆是否曾经被压缩(实际上是去碎片化),从而使高水位线收缩(如果是这样,如何实现)

不管它的行为是什么,它肯定不在你的控制之下

如果没有,那么有人对如何处理这个问题有其他建议吗

理想情况下,重用您自己的
位图
。您没有指出“以使用大量内存的方式处理”到底是什么。但是,如果不改变图像的尺寸或位深度,请将数据复制回原始的
位图
,而不是分配一个新的位图(如果可以)


Android 2.x上的图像处理是为数不多的几个可以证明使用多个进程是合理的地方之一。您将增加在进程之间共享图像数据的开销,但另一个进程有自己的堆(Java和native),因此这可能会给您更多的“空间”。

我假设您已经调用了
Bitmap.recycle()
,但这是我唯一记得的东西,您到目前为止没有提到过。

,没有迹象表明有任何方法可以压缩内存

这是我的变通方法,虽然不太理想,但比以前的行为要好得多:

现在,我在处理过程中故意保留原始位图,然后循环()并将其设为null,以及GC(),但直到分配输出位图之前

这样做的目的是保留外部(位图)空间,并导致我的应用程序耗尽java堆(在处理过程中,在调用recycle()之前),我至少可以通过在较小的图像上重试来捕获和处理java堆。(以前,在我试图救人之前,一切似乎都很好,但那时已经太晚了,无法恢复。)

从技术上讲,这将我的最大图像大小限制为小于分配的内存所能达到的大小(因为我需要在堆和外部同时保留空间,而事实上我从不同时需要这两个空间),但至少我仍然可以处理合理的图像大小

之前发生的事情是,我会提前释放并回收位图,这使得java堆上的高水位标记基本上耗尽了我分配的所有内存,这意味着从那时起,我根本无法打开或创建更多的位图(有时除了极小的缩略图)


在我看来,这是android处理位图内存的一个主要缺陷,但我相信它在较新版本的操作系统中已经修复,因此希望我可以在操作系统发布时禁用此解决方法。

是的,这是一个棘手的问题。这在Acer Liquid上尤其糟糕。我想SQLite本机代码也有类似的问题。游标原生init方法通常会失败,并出现类似的症状。是的,我有。(我有一个与此相关的糟糕的解决方案——请参阅我在另一个帖子中的评论。)我只是偶然发现了这篇文章。这可能有用!我最初希望重用原始位图,这将是理想的,因为输出实际上是相同的。问题是,从文件解码位图时,返回的位图是不可变的。(有一个“请求”的标志,它是可变的,但不是在2.3中。)在我的例子中,一个单独的进程不会有多大帮助,因为几乎所有的内存都被位图加载->进程->位图保存的链使用。(我提出了一个差劲但可行的解决方案,我将作为答案发布。)我将更新我的描述以澄清“以某种方式处理…”。请注意:您可能知道这一点,但调用System.gc()不会在调用垃圾回收时立即启动它。它会发出GC被请求的信号,系统会在它认为合适的时候这样做……我认为这值得在官方的android邮件列表上写一个帖子。幸运的是,谷歌会有人帮你。