Android中的位图

我有一些关于位图对象和内存及其一般分类的问题。

  1. 什么是内存或本地位图?
  2. 位图内存与堆内存有什么不同?

支持Bitmap对象的内存是使用本地代码( malloc() )分配的,而不是Java new关键字。 这意味着内存由操作系统直接pipe理,而不是由Dalvikpipe理。

本地堆和Dalvik堆之间唯一真正的区别是Dalvik的堆是垃圾回收,而本地堆不是。

尽pipe如此,这里没有太大的区别。 当你的Bitmap对象被垃圾收集时,它的析构函数会回收本地堆中相关的内存。

资源:

这里有一个很重要的细微之处:尽pipeBitmap像素被分配在本地堆中,但Dalvik中的一些特殊技巧使得它被计入Java堆中。 这是由于两个原因:

(1)控制应用程序分配的内存量。 没有会计,应用程序可以分配大量的内存(因为Bitmap对象本身非常小,可以容纳任意大量的本机内存),扩展超过了16MB或24MB堆的限制。

(2)帮助确定何时进行GC。 没有会计,你可以分配和释放所说的100个位图对象的引用; GC不会运行,因为这些对象很小,但实际上它们可能代表了大量实际分配的兆字节,而这些分配现在没有及时进行。 通过对Java堆计算这些分配,垃圾收集器将按照它认为正在使用的内存运行。

请注意,在许多方面这是一个实现细节; 它很可能会在将来发生变化,尽pipe这种基本的行为仍然会以某种forms存在,因为这些都是pipe理位图分配的重要特征。

从野外部署,我发现了以下设备:

  • 限制在java堆的16 MiB的设备(位图几乎是无限的)。
  • (java堆+本地位图存储)限制为16 MiB的设备
  • 限制为24MB Java堆的设备(位图几乎是无限的)。
  • (java堆+本地位图存储)限制为24 MiB的设备

24 MiB往往是高分辨率设备,可以使用Runtime.getRuntime()。maxMemory()来检测。 现在还有32MiB设备,一些根植的手机默认有64MiB。 以前,我多次困惑自己,试图弄清楚发生了什么。 我认为所有设备都将位图计入堆限制中。 但是对于机器人队伍的概括是非常困难的。

这是一个非常讨厌的问题在Android上,非常混乱。 这种限制和它的行为logging不完善,复杂而且非常不直观。 它们在不同的设备和操作系统版本上也有所不同,并且有几个已知的错误 部分问题是限制不准确 – 由于堆碎片,你会在实际限制之前打到OOM,并且必须保守地留下一两个缓冲区。 更糟糕的是,在出现java OOMexception之前,我有几个设备出现了本地段错误(100%是Android本身的错误),因此永远达不到极限是非常重要的,因为您甚至无法捕捉本机崩溃。 有关我的调查的更多细节,请查看这篇文章 。 在同一篇文章中,我解释了如何衡量使用限制和避免崩溃。

java堆的大小是Runtime.getRuntime()。totalMemory()。

没有简单的方法来测量本地位图存储的大小。 整个本机堆可以用Debug.getNativeHeapAllocatedSize()来衡量,但只有位图计算的极限(我认为)。

我们可以通过在清单文件中使用android:largeheap="true"来增加堆大小。 这将解决你的一些问题。